diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3643/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3643/FixtureByCode.cs
new file mode 100644
index 0000000000..7f40824898
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3643/FixtureByCode.cs
@@ -0,0 +1,130 @@
+//------------------------------------------------------------------------------
+//
+// 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 NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Linq;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3643
+{
+ using System.Threading.Tasks;
+ using System.Threading;
+ [TestFixture]
+ public class FixtureByCodeAsync : TestCaseMappingByCode
+ {
+ protected override void Configure(Configuration configuration)
+ {
+ configuration.SetProperty(Environment.UseQueryCache, "true");
+ configuration.SetProperty(Environment.GenerateStatistics, "true");
+ }
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+
+ mapper.Class(
+ rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Bag(
+ x => x.Children,
+ m =>
+ {
+ m.Access(Accessor.Field);
+ m.Key(k => k.Column("EntityId"));
+ },
+ r => r.OneToMany());
+
+ rc.Cache(
+ cm =>
+ {
+ cm.Include(CacheInclude.All);
+ cm.Usage(CacheUsage.ReadWrite);
+ });
+ });
+
+ mapper.Class(
+ rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Cache(
+ cm =>
+ {
+ cm.Include(CacheInclude.All);
+ cm.Usage(CacheUsage.ReadWrite);
+ });
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void OnSetUp()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ session.CreateSQLQuery(
+ "INSERT INTO Entity (Id) VALUES (0)"
+ ).ExecuteUpdate();
+
+ session.CreateSQLQuery(
+ "INSERT INTO ChildEntity (Id, EntityId) VALUES (0, 0)"
+ ).ExecuteUpdate();
+
+ session.CreateSQLQuery(
+ "INSERT INTO ChildEntity (Id, EntityId) VALUES (1, 0)"
+ ).ExecuteUpdate();
+
+ transaction.Commit();
+ }
+
+ protected override void OnTearDown()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ session.CreateSQLQuery("DELETE FROM ChildEntity").ExecuteUpdate();
+ session.CreateSQLQuery("DELETE FROM Entity").ExecuteUpdate();
+
+ transaction.Commit();
+ }
+
+ [Test]
+ public async Task LoadsEntityWithEnumIdAndChildrenUsingQueryCacheAsync()
+ {
+ await (LoadEntityWithQueryCacheAsync()); // warm up cache
+
+ var entity = await (LoadEntityWithQueryCacheAsync());
+
+ Assert.That(entity.Children.Count(), Is.EqualTo(2));
+
+ Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
+ Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
+ Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
+ }
+
+ private async Task LoadEntityWithQueryCacheAsync(CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+ var entity = (await (session
+ .Query()
+ .FetchMany(x => x.Children)
+ .WithOptions(opt => opt.SetCacheable(true))
+ .ToListAsync(cancellationToken)))[0];
+
+ await (transaction.CommitAsync(cancellationToken));
+ return entity;
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3643/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH3643/Entity.cs
new file mode 100644
index 0000000000..60a3de3c86
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3643/Entity.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+// ReSharper disable CollectionNeverUpdated.Local
+// ReSharper disable UnassignedGetOnlyAutoProperty
+
+namespace NHibernate.Test.NHSpecificTest.GH3643
+{
+ class Entity
+ {
+ private readonly ICollection _children = new List();
+ public virtual EntityId Id { get; protected set; }
+ public virtual IEnumerable Children => _children.AsEnumerable();
+ }
+
+ class ChildEntity
+ {
+ public virtual int Id { get; protected set; }
+ }
+
+ enum EntityId
+ {
+ Id1,
+ Id2
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3643/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH3643/FixtureByCode.cs
new file mode 100644
index 0000000000..c2694e3b63
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3643/FixtureByCode.cs
@@ -0,0 +1,118 @@
+using System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Linq;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3643
+{
+ [TestFixture]
+ public class FixtureByCode : TestCaseMappingByCode
+ {
+ protected override void Configure(Configuration configuration)
+ {
+ configuration.SetProperty(Environment.UseQueryCache, "true");
+ configuration.SetProperty(Environment.GenerateStatistics, "true");
+ }
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+
+ mapper.Class(
+ rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Bag(
+ x => x.Children,
+ m =>
+ {
+ m.Access(Accessor.Field);
+ m.Key(k => k.Column("EntityId"));
+ },
+ r => r.OneToMany());
+
+ rc.Cache(
+ cm =>
+ {
+ cm.Include(CacheInclude.All);
+ cm.Usage(CacheUsage.ReadWrite);
+ });
+ });
+
+ mapper.Class(
+ rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Cache(
+ cm =>
+ {
+ cm.Include(CacheInclude.All);
+ cm.Usage(CacheUsage.ReadWrite);
+ });
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void OnSetUp()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ session.CreateSQLQuery(
+ "INSERT INTO Entity (Id) VALUES (0)"
+ ).ExecuteUpdate();
+
+ session.CreateSQLQuery(
+ "INSERT INTO ChildEntity (Id, EntityId) VALUES (0, 0)"
+ ).ExecuteUpdate();
+
+ session.CreateSQLQuery(
+ "INSERT INTO ChildEntity (Id, EntityId) VALUES (1, 0)"
+ ).ExecuteUpdate();
+
+ transaction.Commit();
+ }
+
+ protected override void OnTearDown()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ session.CreateSQLQuery("DELETE FROM ChildEntity").ExecuteUpdate();
+ session.CreateSQLQuery("DELETE FROM Entity").ExecuteUpdate();
+
+ transaction.Commit();
+ }
+
+ [Test]
+ public void LoadsEntityWithEnumIdAndChildrenUsingQueryCache()
+ {
+ LoadEntityWithQueryCache(); // warm up cache
+
+ var entity = LoadEntityWithQueryCache();
+
+ Assert.That(entity.Children.Count(), Is.EqualTo(2));
+
+ Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
+ Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
+ Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
+ }
+
+ private Entity LoadEntityWithQueryCache()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+ var entity = session
+ .Query()
+ .FetchMany(x => x.Children)
+ .WithOptions(opt => opt.SetCacheable(true))
+ .ToList()[0];
+
+ transaction.Commit();
+ return entity;
+ }
+ }
+}
diff --git a/src/NHibernate.sln.DotSettings b/src/NHibernate.sln.DotSettings
index d78384192e..b77ef433c2 100644
--- a/src/NHibernate.sln.DotSettings
+++ b/src/NHibernate.sln.DotSettings
@@ -21,6 +21,9 @@
<Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="_" Suffix="" Style="aaBb" /></Policy>
True
True
True
@@ -29,6 +32,7 @@
True
True
True
+ True
True
True
True