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())
{