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); }