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)