diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH2627/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH2627/Fixture.cs
new file mode 100644
index 00000000000..ac24f9f72c5
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH2627/Fixture.cs
@@ -0,0 +1,69 @@
+//------------------------------------------------------------------------------
+//
+// 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.Linq;
+using NUnit.Framework;
+using NHibernate.Linq;
+
+namespace NHibernate.Test.NHSpecificTest.GH2627
+{
+ using System.Threading.Tasks;
+ [TestFixture]
+ public class FixtureAsync : BugTestCase
+ {
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var e1 = new Entity {Name = "Bob"};
+ session.Save(e1);
+
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from Child").ExecuteUpdate();
+ session.CreateQuery("delete from System.Object").ExecuteUpdate();
+
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public async Task NullRefInMergeAsync()
+ {
+ Child child;
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ child = new Child
+ {
+ Parent = await (session.Query().FirstOrDefaultAsync()),
+ Name = "John"
+ };
+
+ await (t.CommitAsync());
+ }
+
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ await (session.MergeAsync(child));
+ await (t.CommitAsync());
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2627/Child.cs b/src/NHibernate.Test/NHSpecificTest/GH2627/Child.cs
new file mode 100644
index 00000000000..55ac0288207
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2627/Child.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH2627
+{
+ public class Child
+ {
+ public virtual Guid Id { get; set; }
+ public virtual Entity Parent { get; set; }
+ public virtual string Name { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2627/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH2627/Entity.cs
new file mode 100644
index 00000000000..8757939fdf4
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2627/Entity.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH2627
+{
+ public class Entity
+ {
+ public virtual Guid Id { get; set; }
+ public virtual string Name { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2627/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH2627/Fixture.cs
new file mode 100644
index 00000000000..44f36d3a503
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2627/Fixture.cs
@@ -0,0 +1,57 @@
+using System.Linq;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH2627
+{
+ [TestFixture]
+ public class Fixture : BugTestCase
+ {
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var e1 = new Entity {Name = "Bob"};
+ session.Save(e1);
+
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from Child").ExecuteUpdate();
+ session.CreateQuery("delete from System.Object").ExecuteUpdate();
+
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public void NullRefInMerge()
+ {
+ Child child;
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ child = new Child
+ {
+ Parent = session.Query().FirstOrDefault(),
+ Name = "John"
+ };
+
+ t.Commit();
+ }
+
+ using (var session = OpenSession())
+ using (var t = session.BeginTransaction())
+ {
+ session.Merge(child);
+ t.Commit();
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH2627/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH2627/Mappings.hbm.xml
new file mode 100644
index 00000000000..6c4296a93e9
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH2627/Mappings.hbm.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/NHibernate/Async/Type/ManyToOneType.cs b/src/NHibernate/Async/Type/ManyToOneType.cs
index e288555bddb..d5615a85d7a 100644
--- a/src/NHibernate/Async/Type/ManyToOneType.cs
+++ b/src/NHibernate/Async/Type/ManyToOneType.cs
@@ -11,7 +11,7 @@
using System;
using System.Data.Common;
using NHibernate.Engine;
-using NHibernate.Persister.Entity;
+using NHibernate.Proxy;
using NHibernate.SqlTypes;
using NHibernate.Util;
diff --git a/src/NHibernate/Type/ManyToOneType.cs b/src/NHibernate/Type/ManyToOneType.cs
index b38fb35eba8..172bc8f1b99 100644
--- a/src/NHibernate/Type/ManyToOneType.cs
+++ b/src/NHibernate/Type/ManyToOneType.cs
@@ -1,7 +1,7 @@
using System;
using System.Data.Common;
using NHibernate.Engine;
-using NHibernate.Persister.Entity;
+using NHibernate.Proxy;
using NHibernate.SqlTypes;
using NHibernate.Util;
@@ -162,14 +162,24 @@ private bool IsIdentifier(object value, ISessionImplementor session)
public override bool IsNull(object owner, ISessionImplementor session)
{
- if (IsNullable && !string.IsNullOrEmpty(PropertyName))
- {
- EntityEntry entry = session.PersistenceContext.GetEntry(owner);
+ if (!IsNullable || string.IsNullOrEmpty(PropertyName) || owner == null)
+ return false;
- return session.PersistenceContext.IsPropertyNull(entry.EntityKey, PropertyName);
- }
+ var entityKey = GetEntityKey(owner, session);
+ if (entityKey == null)
+ return false;
- return false;
+ return session.PersistenceContext.IsPropertyNull(entityKey, PropertyName);
+ }
+
+ private static EntityKey GetEntityKey(object owner, ISessionImplementor session)
+ {
+ var entry = session.PersistenceContext.GetEntry(owner);
+ if (entry != null)
+ return entry.EntityKey;
+ if (owner is INHibernateProxy proxy)
+ return session.GenerateEntityKey(proxy.HibernateLazyInitializer.Identifier, session.Factory.GetEntityPersister(proxy.HibernateLazyInitializer.EntityName));
+ return null;
}
public override object Disassemble(object value, ISessionImplementor session, object owner)