From 971b0b0fcdb3688d1e5a03ab009e83ea56b2ac9d Mon Sep 17 00:00:00 2001 From: Ievgen Galamai Date: Tue, 9 Jun 2020 12:56:58 +0300 Subject: [PATCH 1/3] #2414 fix error when query with delayed insert entity in where expression --- .../NHSpecificTest/GH2414/Entity.cs | 10 +++ .../NHSpecificTest/GH2414/Fixture.cs | 86 +++++++++++++++++++ src/NHibernate/Type/NullableType.cs | 10 +++ 3 files changed, 106 insertions(+) create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2414/Entity.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs diff --git a/src/NHibernate.Test/NHSpecificTest/GH2414/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH2414/Entity.cs new file mode 100644 index 00000000000..61b9453e72e --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2414/Entity.cs @@ -0,0 +1,10 @@ +using System; + +namespace NHibernate.Test.NHSpecificTest.GH2414 +{ + class Entity + { + public virtual int Id { get; set; } + public virtual string Name { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs new file mode 100644 index 00000000000..dd541e93c22 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs @@ -0,0 +1,86 @@ +using System.Linq; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH2414 +{ + /// + /// Fixture using 'by code' mappings + /// + /// + /// This fixture is identical to except the mapping is performed + /// by code in the GetMappings method, and does not require the Mappings.hbm.xml file. Use this approach + /// if you prefer. + /// + [TestFixture] + public class Fixture : TestCaseMappingByCode + { + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.Class(rc => + { + rc.Id(x => x.Id, m => m.Generator(Generators.Identity)); + rc.Property(x => x.Name); + }); + + 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(); + } + } + + 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 QueryWithEqualDelayedPostInsertIdentifierInWhere() + { + using (var session = OpenSession()) + { + var entity = new Entity() { Name = "NewEntity" }; + session.Persist(entity); + var result = session.Query().Where(x => x == entity).ToList(); + Assert.That(result, Has.Count.EqualTo(0)); + } + } + + [Test] + public void QueryWithNotEqualDelayedPostInsertIdentifierInWhere() + { + using (var session = OpenSession()) + { + var entity = new Entity() { Name = "NewEntity" }; + session.Persist(entity); + var result = session.Query().Where(x => x != entity).ToList(); + Assert.That(result, Has.Count.EqualTo(2)); + } + } + } +} diff --git a/src/NHibernate/Type/NullableType.cs b/src/NHibernate/Type/NullableType.cs index e84b6df48da..08e0a173a56 100644 --- a/src/NHibernate/Type/NullableType.cs +++ b/src/NHibernate/Type/NullableType.cs @@ -1,5 +1,6 @@ using System; using System.Data.Common; +using NHibernate.Action; using NHibernate.Engine; using NHibernate.SqlTypes; using NHibernate.Util; @@ -152,6 +153,15 @@ public sealed override void NullSafeSet(DbCommand st, object value, int index, I // I definitely need to look into this more... st.Parameters[index].Value = DBNull.Value; } + else if (value is DelayedPostInsertIdentifier) + { + if (IsDebugEnabled) + { + Log.Debug("binding 0 to parameter: {0}", index); + } + + st.Parameters[index].Value = 0; + } else { if (IsDebugEnabled) From 2064694c65885374cf3a45dd46703f0f4a71024d Mon Sep 17 00:00:00 2001 From: Ievgen Galamai Date: Mon, 15 Jun 2020 15:17:55 +0300 Subject: [PATCH 2/3] #2414 Add new tests --- .../GH2414/EntityWithGuidKey.cs | 14 +++++++++++ .../NHSpecificTest/GH2414/Fixture.cs | 25 ++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2414/EntityWithGuidKey.cs diff --git a/src/NHibernate.Test/NHSpecificTest/GH2414/EntityWithGuidKey.cs b/src/NHibernate.Test/NHSpecificTest/GH2414/EntityWithGuidKey.cs new file mode 100644 index 00000000000..ae61b78752a --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2414/EntityWithGuidKey.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NHibernate.Test.NHSpecificTest.GH2414 +{ + class EntityWithGuidKey + { + public virtual Guid Id { get; set; } + public virtual string Name { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs index dd541e93c22..90e36a08904 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using NHibernate.Cfg.MappingSchema; using NHibernate.Mapping.ByCode; using NUnit.Framework; @@ -24,6 +25,11 @@ protected override HbmMapping GetMappings() rc.Id(x => x.Id, m => m.Generator(Generators.Identity)); rc.Property(x => x.Name); }); + mapper.Class(rc => + { + rc.Id(x => x.Id, m => m.Generator(Generators.Guid)); + rc.Property(x => x.Name); + }); return mapper.CompileMappingForAllExplicitlyAddedEntities(); } @@ -39,6 +45,11 @@ protected override void OnSetUp() var e2 = new Entity { Name = "Sally" }; session.Save(e2); + var e3 = new EntityWithGuidKey() { Id = Guid.NewGuid(), Name = "Bob" }; + session.Save(e3); + + var e4 = new EntityWithGuidKey() { Id = Guid.NewGuid(), Name = "Sally" }; + transaction.Commit(); } } @@ -71,6 +82,18 @@ public void QueryWithEqualDelayedPostInsertIdentifierInWhere() } } + [Test] + public void QueryWithEqualDelayedPostInsertIdentifierInWhereWithGuidKeyEntity() + { + using (var session = OpenSession()) + { + var entity = new EntityWithGuidKey() { Name = "NewEntity" }; + session.Persist(entity); + var result = session.Query().Where(x => x == entity).ToList(); + Assert.That(result, Has.Count.EqualTo(0)); + } + } + [Test] public void QueryWithNotEqualDelayedPostInsertIdentifierInWhere() { From 4a68d56f0d7d62bcf7ea7ec4fb470b8a330e01dc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Aug 2022 22:55:58 +0000 Subject: [PATCH 3/3] Generate async files --- .../Async/NHSpecificTest/GH2414/Fixture.cs | 121 ++++++++++++++++++ src/NHibernate/Async/Type/NullableType.cs | 1 + 2 files changed, 122 insertions(+) create mode 100644 src/NHibernate.Test/Async/NHSpecificTest/GH2414/Fixture.cs diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH2414/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH2414/Fixture.cs new file mode 100644 index 00000000000..ac1af8f959f --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH2414/Fixture.cs @@ -0,0 +1,121 @@ +//------------------------------------------------------------------------------ +// +// 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.Mapping.ByCode; +using NUnit.Framework; +using NHibernate.Linq; + +namespace NHibernate.Test.NHSpecificTest.GH2414 +{ + using System.Threading.Tasks; + /// + /// Fixture using 'by code' mappings + /// + /// + /// This fixture is identical to except the mapping is performed + /// by code in the GetMappings method, and does not require the Mappings.hbm.xml file. Use this approach + /// if you prefer. + /// + [TestFixture] + public class FixtureAsync : TestCaseMappingByCode + { + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.Class(rc => + { + rc.Id(x => x.Id, m => m.Generator(Generators.Identity)); + rc.Property(x => x.Name); + }); + mapper.Class(rc => + { + rc.Id(x => x.Id, m => m.Generator(Generators.Guid)); + rc.Property(x => x.Name); + }); + + 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); + + var e3 = new EntityWithGuidKey() { Id = Guid.NewGuid(), Name = "Bob" }; + session.Save(e3); + + var e4 = new EntityWithGuidKey() { Id = Guid.NewGuid(), Name = "Sally" }; + + transaction.Commit(); + } + } + + 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 QueryWithEqualDelayedPostInsertIdentifierInWhereAsync() + { + using (var session = OpenSession()) + { + var entity = new Entity() { Name = "NewEntity" }; + await (session.PersistAsync(entity)); + var result = await (session.Query().Where(x => x == entity).ToListAsync()); + Assert.That(result, Has.Count.EqualTo(0)); + } + } + + [Test] + public async Task QueryWithEqualDelayedPostInsertIdentifierInWhereWithGuidKeyEntityAsync() + { + using (var session = OpenSession()) + { + var entity = new EntityWithGuidKey() { Name = "NewEntity" }; + await (session.PersistAsync(entity)); + var result = await (session.Query().Where(x => x == entity).ToListAsync()); + Assert.That(result, Has.Count.EqualTo(0)); + } + } + + [Test] + public async Task QueryWithNotEqualDelayedPostInsertIdentifierInWhereAsync() + { + using (var session = OpenSession()) + { + var entity = new Entity() { Name = "NewEntity" }; + await (session.PersistAsync(entity)); + var result = await (session.Query().Where(x => x != entity).ToListAsync()); + Assert.That(result, Has.Count.EqualTo(2)); + } + } + } +} diff --git a/src/NHibernate/Async/Type/NullableType.cs b/src/NHibernate/Async/Type/NullableType.cs index 02eb315a461..6cfa0ae1a6a 100644 --- a/src/NHibernate/Async/Type/NullableType.cs +++ b/src/NHibernate/Async/Type/NullableType.cs @@ -10,6 +10,7 @@ using System; using System.Data.Common; +using NHibernate.Action; using NHibernate.Engine; using NHibernate.SqlTypes; using NHibernate.Util;