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.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/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 new file mode 100644 index 00000000000..90e36a08904 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2414/Fixture.cs @@ -0,0 +1,109 @@ +using System; +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); + }); + 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 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 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() + { + 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/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; diff --git a/src/NHibernate/Type/NullableType.cs b/src/NHibernate/Type/NullableType.cs index 883894ee971..683c40e9159 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)