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)