diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3289/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3289/FixtureByCode.cs
new file mode 100644
index 00000000000..721d35848ab
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3289/FixtureByCode.cs
@@ -0,0 +1,111 @@
+//------------------------------------------------------------------------------
+//
+// 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.MappingSchema;
+using NHibernate.Linq;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3289
+{
+ using System.Threading.Tasks;
+ [TestFixture]
+ public class ByCodeFixtureAsync : 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);
+ rc.Component(x => x.Component);
+ });
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.Identity));
+ rc.Property(x => x.Name);
+ rc.Component(x => x.Component);
+ });
+ mapper.JoinedSubclass(rc =>
+ {
+ rc.Key(k => k.Column("Id"));
+ rc.Property(x => x.SomeProperty);
+ });
+ mapper.Component(rc =>
+ {
+ rc.Property(x => x.Field);
+ rc.Lazy(true);
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void OnSetUp()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+ var e1 = new SubEntity { Name = "Jim" };
+ session.Save(e1);
+
+ transaction.Commit();
+ }
+
+ protected override void OnTearDown()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ if (Dialect.SupportsTemporaryTables)
+ session.CreateQuery("delete from System.Object").ExecuteUpdate();
+ else
+ session.Delete("from System.Object");
+
+ transaction.Commit();
+ }
+
+ [Test]
+ public async Task TestSubEntityInterfaceWithFetchIsPropertyInitializedAsync()
+ {
+ using var session = OpenSession();
+ var data = await (session.Query()
+ .Fetch(e => e.Component)
+ .ToListAsync());
+ var result = NHibernateUtil.IsPropertyInitialized(data[0], "Component");
+
+ Assert.That(result, Is.True);
+ }
+
+ [Test]
+ public async Task TestEntityInterfaceWithFetchIsPropertyInitializedAsync()
+ {
+ using var session = OpenSession();
+ var data = await (session.Query()
+ .Fetch(e => e.Component)
+ .ToListAsync());
+ var result = NHibernateUtil.IsPropertyInitialized(data[0], "Component");
+
+ Assert.That(result, Is.True);
+ }
+
+ [Test]
+ public async Task TestSubEntityWithFetchIsPropertyInitializedAsync()
+ {
+ using var session = OpenSession();
+ var data = await (session.Query()
+ .Fetch(e => e.Component)
+ .ToListAsync());
+ var result = NHibernateUtil.IsPropertyInitialized(data[0], "Component");
+
+ Assert.That(result, Is.True);
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3289/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH3289/FixtureByCode.cs
new file mode 100644
index 00000000000..8bc20205c12
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3289/FixtureByCode.cs
@@ -0,0 +1,100 @@
+using System.Linq;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Linq;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3289
+{
+ [TestFixture]
+ public class ByCodeFixture : 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);
+ rc.Component(x => x.Component);
+ });
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id, m => m.Generator(Generators.Identity));
+ rc.Property(x => x.Name);
+ rc.Component(x => x.Component);
+ });
+ mapper.JoinedSubclass(rc =>
+ {
+ rc.Key(k => k.Column("Id"));
+ rc.Property(x => x.SomeProperty);
+ });
+ mapper.Component(rc =>
+ {
+ rc.Property(x => x.Field);
+ rc.Lazy(true);
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void OnSetUp()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+ var e1 = new SubEntity { Name = "Jim" };
+ session.Save(e1);
+
+ transaction.Commit();
+ }
+
+ protected override void OnTearDown()
+ {
+ using var session = OpenSession();
+ using var transaction = session.BeginTransaction();
+
+ if (Dialect.SupportsTemporaryTables)
+ session.CreateQuery("delete from System.Object").ExecuteUpdate();
+ else
+ session.Delete("from System.Object");
+
+ transaction.Commit();
+ }
+
+ [Test]
+ public void TestSubEntityInterfaceWithFetchIsPropertyInitialized()
+ {
+ using var session = OpenSession();
+ var data = session.Query()
+ .Fetch(e => e.Component)
+ .ToList();
+ var result = NHibernateUtil.IsPropertyInitialized(data[0], "Component");
+
+ Assert.That(result, Is.True);
+ }
+
+ [Test]
+ public void TestEntityInterfaceWithFetchIsPropertyInitialized()
+ {
+ using var session = OpenSession();
+ var data = session.Query()
+ .Fetch(e => e.Component)
+ .ToList();
+ var result = NHibernateUtil.IsPropertyInitialized(data[0], "Component");
+
+ Assert.That(result, Is.True);
+ }
+
+ [Test]
+ public void TestSubEntityWithFetchIsPropertyInitialized()
+ {
+ using var session = OpenSession();
+ var data = session.Query()
+ .Fetch(e => e.Component)
+ .ToList();
+ var result = NHibernateUtil.IsPropertyInitialized(data[0], "Component");
+
+ Assert.That(result, Is.True);
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3289/Models.cs b/src/NHibernate.Test/NHSpecificTest/GH3289/Models.cs
new file mode 100644
index 00000000000..ffbbeeb7bf7
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3289/Models.cs
@@ -0,0 +1,37 @@
+namespace NHibernate.Test.NHSpecificTest.GH3289
+{
+ public interface IEntity
+ {
+ int Id { get; set; }
+ string Name { get; set; }
+ Component Component { get; set; }
+ }
+
+ public interface ISubEntity : IEntity
+ {
+ public bool SomeProperty { get; set; }
+ }
+
+ public class Entity : IEntity
+ {
+ public virtual int Id { get; set; }
+ public virtual string Name { get; set; }
+ public virtual Component Component { get; set; }
+ }
+ public class OtherEntity : IEntity
+ {
+ public virtual int Id { get; set; }
+ public virtual string Name { get; set; }
+ public virtual Component Component { get; set; }
+ }
+
+ public class SubEntity : Entity, ISubEntity
+ {
+ public virtual bool SomeProperty { get; set; }
+ }
+
+ public class Component
+ {
+ public virtual string Field { get; set; }
+ }
+}
diff --git a/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs b/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs
index a042af3c12d..31401f7df81 100644
--- a/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs
+++ b/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs
@@ -52,6 +52,16 @@ private void Process(
{
var metadata = queryModelVisitor.VisitorParameters.SessionFactory
.GetClassMetadata(resultOperator.RelationMember.ReflectedType);
+ if (metadata == null)
+ {
+ var entityName = queryModelVisitor.VisitorParameters.SessionFactory.GetImplementors(
+ resultOperator.RelationMember.ReflectedType.FullName).FirstOrDefault();
+ if (!string.IsNullOrEmpty(entityName))
+ {
+ metadata = queryModelVisitor.VisitorParameters.SessionFactory.GetClassMetadata(entityName);
+ }
+ }
+
propType = metadata?.GetPropertyType(resultOperator.RelationMember.Name);
}