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..71b43faf92
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3643/FixtureByCode.cs
@@ -0,0 +1,124 @@
+//------------------------------------------------------------------------------
+//
+// 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"));
+ m.Cascade(Mapping.ByCode.Cascade.All);
+ },
+ 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();
+
+ var entity = new Entity { Id = EntityId.Id1 };
+ entity.Children.Add(new ChildEntity { Id = 0 });
+ entity.Children.Add(new ChildEntity { Id = 1 });
+ session.Save(entity);
+
+ transaction.Commit();
+ }
+
+ protected override void OnTearDown()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ session.CreateQuery("delete from ChildEntity").ExecuteUpdate();
+ session.CreateQuery("delete from System.Object").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..09f08d8dba
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3643/Entity.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+// ReSharper disable CollectionNeverUpdated.Local
+// ReSharper disable UnassignedGetOnlyAutoProperty
+
+namespace NHibernate.Test.NHSpecificTest.GH3643
+{
+ class Entity
+ {
+ private readonly ICollection _children = [];
+ public virtual EntityId Id { get; set; }
+ public virtual ICollection Children => _children;
+ }
+
+ class ChildEntity
+ {
+ public virtual int Id { get; 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..2fc0741b48
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3643/FixtureByCode.cs
@@ -0,0 +1,112 @@
+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"));
+ m.Cascade(Mapping.ByCode.Cascade.All);
+ },
+ 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();
+
+ var entity = new Entity { Id = EntityId.Id1 };
+ entity.Children.Add(new ChildEntity { Id = 0 });
+ entity.Children.Add(new ChildEntity { Id = 1 });
+ session.Save(entity);
+
+ transaction.Commit();
+ }
+
+ protected override void OnTearDown()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ session.CreateQuery("delete from ChildEntity").ExecuteUpdate();
+ session.CreateQuery("delete from System.Object").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/Async/Type/TypeHelper.cs b/src/NHibernate/Async/Type/TypeHelper.cs
index 3446d11524..0f04ceebb7 100644
--- a/src/NHibernate/Async/Type/TypeHelper.cs
+++ b/src/NHibernate/Async/Type/TypeHelper.cs
@@ -125,6 +125,7 @@ internal static async Task InitializeCollectionsAsync(
continue;
}
+ value = await (pair.Value.KeyType.AssembleAsync(value, session, null, cancellationToken)).ConfigureAwait(false);
var collection = session.PersistenceContext.GetCollection(new CollectionKey(pair.Value, value));
await (collection.ForceInitializationAsync(cancellationToken)).ConfigureAwait(false);
assembleRow[pair.Key] = collection;
diff --git a/src/NHibernate/Type/TypeHelper.cs b/src/NHibernate/Type/TypeHelper.cs
index 1e28e73c8a..d7278d4a38 100644
--- a/src/NHibernate/Type/TypeHelper.cs
+++ b/src/NHibernate/Type/TypeHelper.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using NHibernate.Collection;
@@ -133,6 +133,7 @@ internal static void InitializeCollections(
continue;
}
+ value = pair.Value.KeyType.Assemble(value, session, null);
var collection = session.PersistenceContext.GetCollection(new CollectionKey(pair.Value, value));
collection.ForceInitialization();
assembleRow[pair.Key] = collection;