diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH2043/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH2043/Fixture.cs
new file mode 100644
index 00000000000..6b94d0fc903
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH2043/Fixture.cs
@@ -0,0 +1,304 @@
+//------------------------------------------------------------------------------
+//
+// 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 System.Linq;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Engine;
+using NHibernate.Mapping.ByCode;
+using NHibernate.Proxy;
+using NUnit.Framework;
+using NHibernate.Linq;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ using System.Threading.Tasks;
+ using System.Threading;
+ [TestFixture]
+ public class FixtureAsync : TestCaseMappingByCode
+ {
+ private Guid _entityWithClassProxy2Id;
+ private Guid _entityWithInterfaceProxy2Id;
+ private Guid _entityWithClassLookupId;
+ private Guid _entityWithInterfaceLookupId;
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Table("ProxyDefinition");
+ rc.Proxy(typeof(EntityWithClassProxyDefinition));
+
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Table("IProxyDefinition");
+ rc.Proxy(typeof(IEntityProxy));
+
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityWithClassProxyDefinition)));
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityWithInterfaceProxyDefinition)));
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.Assigned));
+ rc.Property(x => x.Name);
+ rc.ManyToOne(x => x.Parent);
+ });
+
+ mapper.Class(
+ rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.Assigned));
+ rc.Property(x => x.Name);
+ rc.Bag(
+ x => x.Children,
+ m =>
+ {
+ m.Inverse(true);
+ m.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans);
+ },
+ cm => { cm.OneToMany(); });
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void OnSetUp()
+ {
+ using(var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var entityCP1 = new EntityWithClassProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1"
+ };
+
+ var entityCP2 = new EntityWithClassProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 2"
+ };
+ _entityWithClassProxy2Id = entityCP2.Id;
+
+ var entityIP1 = new EntityWithInterfaceProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1"
+ };
+
+ var entityIP2 = new EntityWithInterfaceProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 2"
+ };
+ _entityWithInterfaceProxy2Id = entityIP2.Id;
+
+ session.Save(entityCP1);
+ session.Save(entityCP2);
+ session.Save(entityIP1);
+ session.Save(entityIP2);
+
+ var entityCL = new EntityWithClassLookup
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1",
+ EntityLookup = (EntityWithClassProxyDefinition)session.Load(typeof(EntityWithClassProxyDefinition), entityCP1.Id)
+ };
+ _entityWithClassLookupId = entityCL.Id;
+
+ var entityIL = new EntityWithInterfaceLookup
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1",
+ EntityLookup = (IEntityProxy)session.Load(typeof(EntityWithInterfaceProxyDefinition), entityIP1.Id)
+ };
+ _entityWithInterfaceLookupId = entityIL.Id;
+
+ session.Save(entityCL);
+ session.Save(entityIL);
+
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.Delete("from System.Object");
+
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public async Task UpdateEntityWithClassLookupAsync()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var entityToUpdate = await (session.Query()
+ .FirstAsync(e => e.Id == _entityWithClassLookupId));
+
+ entityToUpdate.EntityLookup = (EntityWithClassProxyDefinition) await (session.LoadAsync(typeof(EntityWithClassProxyDefinition), _entityWithClassProxy2Id));
+
+ await (session.UpdateAsync(entityToUpdate));
+ await (session.FlushAsync());
+ await (transaction.CommitAsync());
+ }
+ }
+
+ [Test]
+ public async Task UpdateEntityWithInterfaceLookupAsync()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var entityToUpdate = await (session.Query()
+ .FirstAsync(e => e.Id == _entityWithInterfaceLookupId));
+
+ entityToUpdate.EntityLookup = (IEntityProxy) await (session.LoadAsync(typeof(EntityWithInterfaceProxyDefinition), _entityWithInterfaceProxy2Id));
+
+ await (session.UpdateAsync(entityToUpdate));
+ await (session.FlushAsync());
+ await (transaction.CommitAsync());
+ }
+ }
+
+ [Test]
+ public async Task TransientProxySaveAsync()
+ {
+ var id = 10;
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var e = new EntityAssigned() {Id = id, Name = "a"};
+
+ await (session.SaveAsync(e));
+ await (session.FlushAsync());
+ await (t.CommitAsync());
+ }
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var e = await (GetTransientProxyAsync(session, id));
+ await (session.SaveAsync(e));
+ await (session.FlushAsync());
+
+ await (t.CommitAsync());
+ }
+
+ using (var session = OpenSession())
+ {
+ var entity = await (session.GetAsync(id));
+ Assert.That(entity, Is.Not.Null, "Transient proxy wasn't saved");
+ }
+ }
+
+ [Test]
+ public async Task TransientProxyBagCascadeSaveAsync()
+ {
+ var id = 10;
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var e = new EntityAssigned() {Id = id, Name = "a"};
+ await (session.SaveAsync(e));
+ await (session.FlushAsync());
+ await (t.CommitAsync());
+ }
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var child = await (GetTransientProxyAsync(session, id));
+ var parent = new EntityWithAssignedBag()
+ {
+ Id = 1, Name = "p", Children =
+ {
+ child
+ }
+ };
+ child.Parent = parent;
+
+ await (session.SaveAsync(parent));
+ await (session.FlushAsync());
+
+ await (t.CommitAsync());
+ }
+
+ using (var session = OpenSession())
+ {
+ var entity = await (session.GetAsync(id));
+ Assert.That(entity, Is.Not.Null, "Transient proxy wasn't saved");
+ }
+ }
+
+ [Test]
+ public async Task TransientProxyDetectionFromUserCodeAsync()
+ {
+ var id = 10;
+
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ var e = new EntityAssigned() {Id = id, Name = "a"};
+ await (session.SaveAsync(e));
+ await (session.FlushAsync());
+ await (t.CommitAsync());
+ }
+
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ var child = await (GetTransientProxyAsync(session, id));
+ Assert.That(await (ForeignKeys.IsTransientSlowAsync(typeof(EntityAssigned).FullName, child, session.GetSessionImplementation(), CancellationToken.None)), Is.True);
+ await (t.CommitAsync());
+ }
+ }
+
+ private static async Task GetTransientProxyAsync(ISession session, int id, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ EntityAssigned e;
+ e = await (session.LoadAsync(id, cancellationToken));
+ e.Name = "b";
+ await (session.DeleteAsync(e, cancellationToken));
+ await (session.FlushAsync(cancellationToken));
+ Assert.That(e.IsProxy(), Is.True, "Failed test set up");
+ return e;
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/EntityAssigned.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityAssigned.cs
new file mode 100644
index 00000000000..9708e11c7e1
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityAssigned.cs
@@ -0,0 +1,9 @@
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ public class EntityAssigned
+ {
+ public virtual int Id { get; set; }
+ public virtual string Name { get; set; }
+ public virtual EntityWithAssignedBag Parent { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithAssignedBag.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithAssignedBag.cs
new file mode 100644
index 00000000000..a579d3e966e
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithAssignedBag.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ public class EntityWithAssignedBag
+ {
+ public virtual int Id { get; set; }
+ public virtual string Name { get; set; }
+ public virtual IList Children { get; set; } = new List();
+ }
+}
\ No newline at end of file
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithClassLookup.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithClassLookup.cs
new file mode 100644
index 00000000000..637c5ff5bda
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithClassLookup.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ public class EntityWithClassLookup
+ {
+ public virtual Guid Id { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual EntityWithClassProxyDefinition EntityLookup { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithClassProxyDefinition.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithClassProxyDefinition.cs
new file mode 100644
index 00000000000..4829de3012c
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithClassProxyDefinition.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ public class EntityWithClassProxyDefinition
+ {
+ public virtual Guid Id { get; set; }
+
+ public virtual string Name { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithInterfaceLookup.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithInterfaceLookup.cs
new file mode 100644
index 00000000000..6bcee043a49
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithInterfaceLookup.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ public class EntityWithInterfaceLookup
+ {
+ public virtual Guid Id { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual IEntityProxy EntityLookup { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithInterfaceProxyDefinition.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithInterfaceProxyDefinition.cs
new file mode 100644
index 00000000000..198ddadfa4a
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/EntityWithInterfaceProxyDefinition.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ public class EntityWithInterfaceProxyDefinition: IEntityProxy
+ {
+ public virtual Guid Id { get; set; }
+
+ public virtual string Name { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/Fixture.cs
new file mode 100644
index 00000000000..a289226a6fc
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/Fixture.cs
@@ -0,0 +1,291 @@
+using System;
+using System.Linq;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Engine;
+using NHibernate.Mapping.ByCode;
+using NHibernate.Proxy;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ [TestFixture]
+ public class Fixture : TestCaseMappingByCode
+ {
+ private Guid _entityWithClassProxy2Id;
+ private Guid _entityWithInterfaceProxy2Id;
+ private Guid _entityWithClassLookupId;
+ private Guid _entityWithInterfaceLookupId;
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Table("ProxyDefinition");
+ rc.Proxy(typeof(EntityWithClassProxyDefinition));
+
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Table("IProxyDefinition");
+ rc.Proxy(typeof(IEntityProxy));
+
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityWithClassProxyDefinition)));
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ rc.ManyToOne(x => x.EntityLookup, x => x.Class(typeof(EntityWithInterfaceProxyDefinition)));
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.Assigned));
+ rc.Property(x => x.Name);
+ rc.ManyToOne(x => x.Parent);
+ });
+
+ mapper.Class(
+ rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.Assigned));
+ rc.Property(x => x.Name);
+ rc.Bag(
+ x => x.Children,
+ m =>
+ {
+ m.Inverse(true);
+ m.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans);
+ },
+ cm => { cm.OneToMany(); });
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void OnSetUp()
+ {
+ using(var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var entityCP1 = new EntityWithClassProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1"
+ };
+
+ var entityCP2 = new EntityWithClassProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 2"
+ };
+ _entityWithClassProxy2Id = entityCP2.Id;
+
+ var entityIP1 = new EntityWithInterfaceProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1"
+ };
+
+ var entityIP2 = new EntityWithInterfaceProxyDefinition
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 2"
+ };
+ _entityWithInterfaceProxy2Id = entityIP2.Id;
+
+ session.Save(entityCP1);
+ session.Save(entityCP2);
+ session.Save(entityIP1);
+ session.Save(entityIP2);
+
+ var entityCL = new EntityWithClassLookup
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1",
+ EntityLookup = (EntityWithClassProxyDefinition)session.Load(typeof(EntityWithClassProxyDefinition), entityCP1.Id)
+ };
+ _entityWithClassLookupId = entityCL.Id;
+
+ var entityIL = new EntityWithInterfaceLookup
+ {
+ Id = Guid.NewGuid(),
+ Name = "Name 1",
+ EntityLookup = (IEntityProxy)session.Load(typeof(EntityWithInterfaceProxyDefinition), entityIP1.Id)
+ };
+ _entityWithInterfaceLookupId = entityIL.Id;
+
+ session.Save(entityCL);
+ session.Save(entityIL);
+
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.Delete("from System.Object");
+
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public void UpdateEntityWithClassLookup()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var entityToUpdate = session.Query()
+ .First(e => e.Id == _entityWithClassLookupId);
+
+ entityToUpdate.EntityLookup = (EntityWithClassProxyDefinition) session.Load(typeof(EntityWithClassProxyDefinition), _entityWithClassProxy2Id);
+
+ session.Update(entityToUpdate);
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public void UpdateEntityWithInterfaceLookup()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var entityToUpdate = session.Query()
+ .First(e => e.Id == _entityWithInterfaceLookupId);
+
+ entityToUpdate.EntityLookup = (IEntityProxy) session.Load(typeof(EntityWithInterfaceProxyDefinition), _entityWithInterfaceProxy2Id);
+
+ session.Update(entityToUpdate);
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public void TransientProxySave()
+ {
+ var id = 10;
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var e = new EntityAssigned() {Id = id, Name = "a"};
+
+ session.Save(e);
+ session.Flush();
+ t.Commit();
+ }
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var e = GetTransientProxy(session, id);
+ session.Save(e);
+ session.Flush();
+
+ t.Commit();
+ }
+
+ using (var session = OpenSession())
+ {
+ var entity = session.Get(id);
+ Assert.That(entity, Is.Not.Null, "Transient proxy wasn't saved");
+ }
+ }
+
+ [Test]
+ public void TransientProxyBagCascadeSave()
+ {
+ var id = 10;
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var e = new EntityAssigned() {Id = id, Name = "a"};
+ session.Save(e);
+ session.Flush();
+ t.Commit();
+ }
+
+ using (var session = OpenSession())
+ using(var t = session.BeginTransaction())
+ {
+ var child = GetTransientProxy(session, id);
+ var parent = new EntityWithAssignedBag()
+ {
+ Id = 1, Name = "p", Children =
+ {
+ child
+ }
+ };
+ child.Parent = parent;
+
+ session.Save(parent);
+ session.Flush();
+
+ t.Commit();
+ }
+
+ using (var session = OpenSession())
+ {
+ var entity = session.Get(id);
+ Assert.That(entity, Is.Not.Null, "Transient proxy wasn't saved");
+ }
+ }
+
+ [Test]
+ public void TransientProxyDetectionFromUserCode()
+ {
+ var id = 10;
+
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ var e = new EntityAssigned() {Id = id, Name = "a"};
+ session.Save(e);
+ session.Flush();
+ t.Commit();
+ }
+
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ var child = GetTransientProxy(session, id);
+ Assert.That(ForeignKeys.IsTransientSlow(typeof(EntityAssigned).FullName, child, session.GetSessionImplementation()), Is.True);
+ t.Commit();
+ }
+ }
+
+ private static EntityAssigned GetTransientProxy(ISession session, int id)
+ {
+ EntityAssigned e;
+ e = session.Load(id);
+ e.Name = "b";
+ session.Delete(e);
+ session.Flush();
+ Assert.That(e.IsProxy(), Is.True, "Failed test set up");
+ return e;
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2043/IEntityProxy.cs b/src/NHibernate.Test/NHSpecificTest/GH2043/IEntityProxy.cs
new file mode 100644
index 00000000000..76b48d30eb1
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2043/IEntityProxy.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH2043
+{
+ public interface IEntityProxy
+ {
+ Guid Id { get; set; }
+
+ string Name { get; set; }
+ }
+}
diff --git a/src/NHibernate/Async/Engine/ForeignKeys.cs b/src/NHibernate/Async/Engine/ForeignKeys.cs
index 11597f5fcd1..441dbcb87d4 100644
--- a/src/NHibernate/Async/Engine/ForeignKeys.cs
+++ b/src/NHibernate/Async/Engine/ForeignKeys.cs
@@ -181,10 +181,29 @@ public static async Task IsNotTransientSlowAsync(string entityName, object
return false;
}
+ var proxy = entity as INHibernateProxy;
+ if (proxy?.HibernateLazyInitializer.IsUninitialized == true)
+ {
+ return false;
+ }
+
// let the interceptor inspect the instance to decide
+ var interceptorResult = session.Interceptor.IsTransient(entity);
+ if (interceptorResult.HasValue)
+ return interceptorResult;
+
// let the persister inspect the instance to decide
- return session.Interceptor.IsTransient(entity) ??
- await (session.GetEntityPersister(entityName, entity).IsTransientAsync(entity, session, cancellationToken)).ConfigureAwait(false);
+ if (proxy != null)
+ {
+ // The persister only deals with unproxied entities.
+ entity = await (proxy.HibernateLazyInitializer.GetImplementationAsync(cancellationToken)).ConfigureAwait(false);
+ }
+
+ return await (session
+ .GetEntityPersister(
+ entityName,
+ entity)
+ .IsTransientAsync(entity, session, cancellationToken)).ConfigureAwait(false);
}
///
diff --git a/src/NHibernate/Engine/ForeignKeys.cs b/src/NHibernate/Engine/ForeignKeys.cs
index 3c6df63a815..c48dbefaca9 100644
--- a/src/NHibernate/Engine/ForeignKeys.cs
+++ b/src/NHibernate/Engine/ForeignKeys.cs
@@ -178,10 +178,29 @@ public static bool IsNotTransientSlow(string entityName, object entity, ISession
return false;
}
+ var proxy = entity as INHibernateProxy;
+ if (proxy?.HibernateLazyInitializer.IsUninitialized == true)
+ {
+ return false;
+ }
+
// let the interceptor inspect the instance to decide
+ var interceptorResult = session.Interceptor.IsTransient(entity);
+ if (interceptorResult.HasValue)
+ return interceptorResult;
+
// let the persister inspect the instance to decide
- return session.Interceptor.IsTransient(entity) ??
- session.GetEntityPersister(entityName, entity).IsTransient(entity, session);
+ if (proxy != null)
+ {
+ // The persister only deals with unproxied entities.
+ entity = proxy.HibernateLazyInitializer.GetImplementation();
+ }
+
+ return session
+ .GetEntityPersister(
+ entityName,
+ entity)
+ .IsTransient(entity, session);
}
///