diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH2727/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH2727/FixtureByCode.cs new file mode 100644 index 00000000000..b7331f0f382 --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH2727/FixtureByCode.cs @@ -0,0 +1,97 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by AsyncGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +using System; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH2727 +{ + using System.Threading.Tasks; + /// + /// Fixture using 'by code' mappings + /// + [TestFixture] + public class LazyPropByCodeFixtureAsync : TestCaseMappingByCode + { + private Guid id1; + private Guid id2; + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.Class( + rc => + { + rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb)); + rc.Property(x => x.Name); + rc.Property(x => x.LazyProp, m => m.Lazy(true)); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var e1 = new Entity { Name = "Bob" }; + session.Save(e1); + + var e2 = new Entity { Name = "Sally" }; + session.Save(e2); + + transaction.Commit(); + id1 = e1.Id; + id2 = e2.Id; + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + // The HQL delete does all the job inside the database without loading the entities, but it does + // not handle delete order for avoiding violating constraints if any. Use + // session.Delete("from System.Object"); + // instead if in need of having NHbernate ordering the deletes, but this will cause + // loading the entities in the session. + session.CreateQuery("delete from System.Object").ExecuteUpdate(); + + transaction.Commit(); + } + } + + [Test] + public async Task CanLoadUsingInstanceAsync() + { + using (var s = OpenSession()) + { + var e1 = await (s.LoadAsync(id1)); + await (s.LoadAsync(e1, id2)); + } + } + + [Test(Description = "GH-2928")] + public async Task CanSessionRefreshEntityWithLazyPropertiesAsync() + { + using (var s = OpenSession()) + { + var e1 = await (s.GetAsync(id1)); + await (s.RefreshAsync(e1)); + s.Clear(); + await (s.RefreshAsync(e1)); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2727/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH2727/Entity.cs new file mode 100644 index 00000000000..5ef83cd5975 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2727/Entity.cs @@ -0,0 +1,11 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.GH2727 +{ + public class Entity + { + public virtual Guid Id { get; set; } + public virtual string Name { get; set; } + public virtual string LazyProp { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2727/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH2727/FixtureByCode.cs new file mode 100644 index 00000000000..3bd90a97f6e --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2727/FixtureByCode.cs @@ -0,0 +1,86 @@ +using System; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH2727 +{ + /// + /// Fixture using 'by code' mappings + /// + [TestFixture] + public class LazyPropByCodeFixture : TestCaseMappingByCode + { + private Guid id1; + private Guid id2; + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.Class( + rc => + { + rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb)); + rc.Property(x => x.Name); + rc.Property(x => x.LazyProp, m => m.Lazy(true)); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var e1 = new Entity { Name = "Bob" }; + session.Save(e1); + + var e2 = new Entity { Name = "Sally" }; + session.Save(e2); + + transaction.Commit(); + id1 = e1.Id; + id2 = e2.Id; + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + // The HQL delete does all the job inside the database without loading the entities, but it does + // not handle delete order for avoiding violating constraints if any. Use + // session.Delete("from System.Object"); + // instead if in need of having NHbernate ordering the deletes, but this will cause + // loading the entities in the session. + session.CreateQuery("delete from System.Object").ExecuteUpdate(); + + transaction.Commit(); + } + } + + [Test] + public void CanLoadUsingInstance() + { + using (var s = OpenSession()) + { + var e1 = s.Load(id1); + s.Load(e1, id2); + } + } + + [Test(Description = "GH-2928")] + public void CanSessionRefreshEntityWithLazyProperties() + { + using (var s = OpenSession()) + { + var e1 = s.Get(id1); + s.Refresh(e1); + s.Clear(); + s.Refresh(e1); + } + } + } +} diff --git a/src/NHibernate/Async/Event/Default/DefaultLoadEventListener.cs b/src/NHibernate/Async/Event/Default/DefaultLoadEventListener.cs index e71e91aee2b..2ec0cf0bd1e 100644 --- a/src/NHibernate/Async/Event/Default/DefaultLoadEventListener.cs +++ b/src/NHibernate/Async/Event/Default/DefaultLoadEventListener.cs @@ -37,8 +37,8 @@ public virtual async Task OnLoadAsync(LoadEvent @event, LoadType loadType, Cance IEntityPersister persister; if (@event.InstanceToLoad != null) { - persister = source.GetEntityPersister(null, @event.InstanceToLoad); //the load() which takes an entity does not pass an entityName - @event.EntityClassName = @event.InstanceToLoad.GetType().FullName; + @event.EntityClassName = source.BestGuessEntityName(@event.InstanceToLoad); //the load() which takes an entity does not pass an entityName + persister = source.GetEntityPersister(@event.EntityClassName, @event.InstanceToLoad); } else { diff --git a/src/NHibernate/Async/Event/Default/DefaultRefreshEventListener.cs b/src/NHibernate/Async/Event/Default/DefaultRefreshEventListener.cs index 7d745ec2fa3..080c96a70b6 100644 --- a/src/NHibernate/Async/Event/Default/DefaultRefreshEventListener.cs +++ b/src/NHibernate/Async/Event/Default/DefaultRefreshEventListener.cs @@ -68,7 +68,7 @@ public virtual async Task OnRefreshAsync(RefreshEvent @event, IDictionary refres if (e == null) { - persister = source.GetEntityPersister(null, obj); //refresh() does not pass an entityName + persister = source.GetEntityPersister(source.BestGuessEntityName(obj), obj); //refresh() does not pass an entityName id = persister.GetIdentifier(obj); if (log.IsDebugEnabled()) { diff --git a/src/NHibernate/Event/Default/DefaultLoadEventListener.cs b/src/NHibernate/Event/Default/DefaultLoadEventListener.cs index 644cf67d1d1..df7f0287d04 100644 --- a/src/NHibernate/Event/Default/DefaultLoadEventListener.cs +++ b/src/NHibernate/Event/Default/DefaultLoadEventListener.cs @@ -33,8 +33,8 @@ public virtual void OnLoad(LoadEvent @event, LoadType loadType) IEntityPersister persister; if (@event.InstanceToLoad != null) { - persister = source.GetEntityPersister(null, @event.InstanceToLoad); //the load() which takes an entity does not pass an entityName - @event.EntityClassName = @event.InstanceToLoad.GetType().FullName; + @event.EntityClassName = source.BestGuessEntityName(@event.InstanceToLoad); //the load() which takes an entity does not pass an entityName + persister = source.GetEntityPersister(@event.EntityClassName, @event.InstanceToLoad); } else { diff --git a/src/NHibernate/Event/Default/DefaultRefreshEventListener.cs b/src/NHibernate/Event/Default/DefaultRefreshEventListener.cs index 4c04c066859..351fae84db9 100644 --- a/src/NHibernate/Event/Default/DefaultRefreshEventListener.cs +++ b/src/NHibernate/Event/Default/DefaultRefreshEventListener.cs @@ -50,7 +50,7 @@ public virtual void OnRefresh(RefreshEvent @event, IDictionary refreshedAlready) if (e == null) { - persister = source.GetEntityPersister(null, obj); //refresh() does not pass an entityName + persister = source.GetEntityPersister(source.BestGuessEntityName(obj), obj); //refresh() does not pass an entityName id = persister.GetIdentifier(obj); if (log.IsDebugEnabled()) {