diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3421/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3421/Fixture.cs
new file mode 100644
index 0000000000..ed8822a431
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3421/Fixture.cs
@@ -0,0 +1,109 @@
+//------------------------------------------------------------------------------
+//
+// 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.Collections.Generic;
+using System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NHibernate.SqlCommand;
+using NUnit.Framework;
+using NHibernate.Linq;
+
+namespace NHibernate.Test.NHSpecificTest.GH3421
+{
+ using System.Threading.Tasks;
+ [TestFixture]
+ public class ByCodeFixtureAsync : TestCaseMappingByCode
+ {
+ private SqlInterceptor _interceptor;
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.Property(x => x.Name);
+ rc.Component(x => x.Attributes, new {
+ Sku = (string)null
+ }, dc => {
+ dc.Property(x => x.Sku);
+ });
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void Configure(Configuration configuration)
+ {
+ base.Configure(configuration);
+
+ _interceptor = new SqlInterceptor();
+
+ configuration.SetInterceptor(_interceptor);
+ }
+
+ 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", Attributes = new Dictionary() {
+ { "Sku", "AAA" }
+ } };
+ session.Save(e2);
+
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from Entity").ExecuteUpdate();
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public async Task TestFlushDoesNotTriggerAnUpdateAsync()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var foo = await (session.Query().ToListAsync());
+
+ await (session.FlushAsync());
+
+ var updateStatements = _interceptor.SqlStatements.Where(s => s.ToString().ToUpper().Contains("UPDATE")).ToList();
+
+ Assert.That(updateStatements, Has.Count.EqualTo(0));
+ }
+ }
+
+ public class SqlInterceptor : EmptyInterceptor
+ {
+ public IList SqlStatements = new List();
+
+ public override SqlString OnPrepareStatement(SqlString sql)
+ {
+ SqlStatements.Add(sql);
+
+ return base.OnPrepareStatement(sql);
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3421/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH3421/Entity.cs
new file mode 100644
index 0000000000..e208abe904
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3421/Entity.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+
+namespace NHibernate.Test.NHSpecificTest.GH3421
+{
+ class Entity
+ {
+ public virtual Guid Id { get; set; }
+ public virtual string Name { get; set; }
+
+ private IDictionary _attributes;
+ public virtual IDictionary Attributes {
+ get {
+ if (_attributes == null)
+ _attributes = new Dictionary();
+ return _attributes;
+ }
+ set => _attributes = value;
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3421/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH3421/Fixture.cs
new file mode 100644
index 0000000000..4fe7cc6795
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3421/Fixture.cs
@@ -0,0 +1,97 @@
+using System.Collections.Generic;
+using System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NHibernate.SqlCommand;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3421
+{
+ [TestFixture]
+ public class ByCodeFixture : TestCaseMappingByCode
+ {
+ private SqlInterceptor _interceptor;
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.Property(x => x.Name);
+ rc.Component(x => x.Attributes, new {
+ Sku = (string)null
+ }, dc => {
+ dc.Property(x => x.Sku);
+ });
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void Configure(Configuration configuration)
+ {
+ base.Configure(configuration);
+
+ _interceptor = new SqlInterceptor();
+
+ configuration.SetInterceptor(_interceptor);
+ }
+
+ 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", Attributes = new Dictionary() {
+ { "Sku", "AAA" }
+ } };
+ session.Save(e2);
+
+ transaction.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.CreateQuery("delete from Entity").ExecuteUpdate();
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public void TestFlushDoesNotTriggerAnUpdate()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ var foo = session.Query().ToList();
+
+ session.Flush();
+
+ var updateStatements = _interceptor.SqlStatements.Where(s => s.ToString().ToUpper().Contains("UPDATE")).ToList();
+
+ Assert.That(updateStatements, Has.Count.EqualTo(0));
+ }
+ }
+
+ public class SqlInterceptor : EmptyInterceptor
+ {
+ public IList SqlStatements = new List();
+
+ public override SqlString OnPrepareStatement(SqlString sql)
+ {
+ SqlStatements.Add(sql);
+
+ return base.OnPrepareStatement(sql);
+ }
+ }
+ }
+}
diff --git a/src/NHibernate/Async/Type/ComponentType.cs b/src/NHibernate/Async/Type/ComponentType.cs
index 999852e447..6757e22216 100644
--- a/src/NHibernate/Async/Type/ComponentType.cs
+++ b/src/NHibernate/Async/Type/ComponentType.cs
@@ -33,14 +33,6 @@ public override async Task IsDirtyAsync(object x, object y, ISessionImplem
{
return false;
}
- /*
- * NH Different behavior : we don't use the shortcut because NH-1101
- * let the tuplizer choose how cosiderer properties when the component is null.
- */
- if (EntityMode != EntityMode.Poco && (x == null || y == null))
- {
- return true;
- }
object[] xvalues = GetPropertyValues(x);
object[] yvalues = GetPropertyValues(y);
for (int i = 0; i < xvalues.Length; i++)
@@ -60,14 +52,6 @@ public override async Task IsDirtyAsync(object x, object y, bool[] checkab
{
return false;
}
- /*
- * NH Different behavior : we don't use the shortcut because NH-1101
- * let the tuplizer choose how cosiderer properties when the component is null.
- */
- if (EntityMode != EntityMode.Poco && (x == null || y == null))
- {
- return true;
- }
object[] xvalues = GetPropertyValues(x);
object[] yvalues = GetPropertyValues(y);
int loc = 0;
diff --git a/src/NHibernate/Type/ComponentType.cs b/src/NHibernate/Type/ComponentType.cs
index cf9cdbf552..3c3ffe9d2d 100644
--- a/src/NHibernate/Type/ComponentType.cs
+++ b/src/NHibernate/Type/ComponentType.cs
@@ -156,14 +156,6 @@ public override bool IsDirty(object x, object y, ISessionImplementor session)
{
return false;
}
- /*
- * NH Different behavior : we don't use the shortcut because NH-1101
- * let the tuplizer choose how cosiderer properties when the component is null.
- */
- if (EntityMode != EntityMode.Poco && (x == null || y == null))
- {
- return true;
- }
object[] xvalues = GetPropertyValues(x);
object[] yvalues = GetPropertyValues(y);
for (int i = 0; i < xvalues.Length; i++)
@@ -182,14 +174,6 @@ public override bool IsDirty(object x, object y, bool[] checkable, ISessionImple
{
return false;
}
- /*
- * NH Different behavior : we don't use the shortcut because NH-1101
- * let the tuplizer choose how cosiderer properties when the component is null.
- */
- if (EntityMode != EntityMode.Poco && (x == null || y == null))
- {
- return true;
- }
object[] xvalues = GetPropertyValues(x);
object[] yvalues = GetPropertyValues(y);
int loc = 0;