diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3317/FixtureByCode.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3317/FixtureByCode.cs new file mode 100644 index 00000000000..1ca210a186e --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3317/FixtureByCode.cs @@ -0,0 +1,123 @@ +//------------------------------------------------------------------------------ +// +// 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; +using System.Linq; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NHibernate.Linq; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH3317 +{ + using System.Threading.Tasks; + [TestFixture(true)] + [TestFixture(false)] + public class ComponentsListFixtureAsync : TestCaseMappingByCode + { + private readonly bool _fetchJoinMapping; + private Guid _id; + + public ComponentsListFixtureAsync(bool fetchJoinMapping) + { + _fetchJoinMapping = fetchJoinMapping; + } + + protected override void OnSetUp() + { + using var session = OpenSession(); + using var tr = session.BeginTransaction(); + var root = new Entity(); + root.Entries.Add(new ComponentListEntry { ComponentReference = null, DummyString = "one", }); + + session.Save(root); + tr.Commit(); + _id = root.Id; + } + + [Test] + public async Task LazyLoadingAsync() + { + using var newSession = OpenSession(); + var reloadedRoot = await (newSession.GetAsync(_id)); + Assert.AreEqual(1, reloadedRoot.Entries.Count); + } + + [Test] + public async Task QueryOverFetchAsync() + { + using var newSession = OpenSession(); + var reloadedRoot = await (newSession.QueryOver() + .Fetch(SelectMode.Fetch, x => x.Entries) + .Where(x => x.Id == _id) + .SingleOrDefaultAsync()); + Assert.AreEqual(1, reloadedRoot.Entries.Count); + } + + [Test] + public async Task LinqFetchAsync() + { + using var newSession = OpenSession(); + var reloadedRoot = await (newSession.Query() + .Fetch(x => x.Entries) + .Where(x => x.Id == _id) + .SingleOrDefaultAsync()); + Assert.AreEqual(1, reloadedRoot.Entries.Count); + } + + protected override void OnTearDown() + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + session.CreateSQLQuery("delete from Entries").ExecuteUpdate(); + session.Delete("from System.Object"); + transaction.Commit(); + } + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + + mapper.Class(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.GuidComb)); + rc.Lazy(false); + rc.Property(x => x.Name); + + rc.Bag( + x => x.Entries, + v => + { + if (_fetchJoinMapping) + v.Fetch(CollectionFetchMode.Join); + }, + h => h.Component(cmp => + { + cmp.Property(x => x.DummyString); + cmp.ManyToOne(x => x.ComponentReference); + })); + }); + mapper.Class(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.GuidComb)); + rc.Lazy(false); + rc.ManyToOne(x => x.Parent, m => m.NotNullable(true)); + }); + mapper.Class(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.GuidComb)); + rc.Lazy(false); + rc.Property(x => x.Name); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH3317/Entity.cs b/src/NHibernate.Test/NHSpecificTest/GH3317/Entity.cs new file mode 100644 index 00000000000..1e43d5554c1 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH3317/Entity.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.GH3317 +{ + public class Entity + { + public Guid Id { get; set; } + public string Name { get; set; } + public IList Entries { get; set; } = new List(); + } + + public class ComponentListEntry + { + public string DummyString { get; set; } + public EntityWithParent ComponentReference { get; set; } + } + + public class EntityWithParent + { + public Guid Id { get; set; } + public ParentEntity Parent { get; set; } + } + + public class ParentEntity + { + public Guid Id { get; set; } + public string Name { get; set; } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH3317/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH3317/FixtureByCode.cs new file mode 100644 index 00000000000..3847af79449 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH3317/FixtureByCode.cs @@ -0,0 +1,112 @@ +using System; +using System.Linq; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NHibernate.Linq; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH3317 +{ + [TestFixture(true)] + [TestFixture(false)] + public class ComponentsListFixture : TestCaseMappingByCode + { + private readonly bool _fetchJoinMapping; + private Guid _id; + + public ComponentsListFixture(bool fetchJoinMapping) + { + _fetchJoinMapping = fetchJoinMapping; + } + + protected override void OnSetUp() + { + using var session = OpenSession(); + using var tr = session.BeginTransaction(); + var root = new Entity(); + root.Entries.Add(new ComponentListEntry { ComponentReference = null, DummyString = "one", }); + + session.Save(root); + tr.Commit(); + _id = root.Id; + } + + [Test] + public void LazyLoading() + { + using var newSession = OpenSession(); + var reloadedRoot = newSession.Get(_id); + Assert.AreEqual(1, reloadedRoot.Entries.Count); + } + + [Test] + public void QueryOverFetch() + { + using var newSession = OpenSession(); + var reloadedRoot = newSession.QueryOver() + .Fetch(SelectMode.Fetch, x => x.Entries) + .Where(x => x.Id == _id) + .SingleOrDefault(); + Assert.AreEqual(1, reloadedRoot.Entries.Count); + } + + [Test] + public void LinqFetch() + { + using var newSession = OpenSession(); + var reloadedRoot = newSession.Query() + .Fetch(x => x.Entries) + .Where(x => x.Id == _id) + .SingleOrDefault(); + Assert.AreEqual(1, reloadedRoot.Entries.Count); + } + + protected override void OnTearDown() + { + using var session = OpenSession(); + using var transaction = session.BeginTransaction(); + session.CreateSQLQuery("delete from Entries").ExecuteUpdate(); + session.Delete("from System.Object"); + transaction.Commit(); + } + + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + + mapper.Class(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.GuidComb)); + rc.Lazy(false); + rc.Property(x => x.Name); + + rc.Bag( + x => x.Entries, + v => + { + if (_fetchJoinMapping) + v.Fetch(CollectionFetchMode.Join); + }, + h => h.Component(cmp => + { + cmp.Property(x => x.DummyString); + cmp.ManyToOne(x => x.ComponentReference); + })); + }); + mapper.Class(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.GuidComb)); + rc.Lazy(false); + rc.ManyToOne(x => x.Parent, m => m.NotNullable(true)); + }); + mapper.Class(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.GuidComb)); + rc.Lazy(false); + rc.Property(x => x.Name); + }); + + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + } +} diff --git a/src/NHibernate/Loader/JoinWalker.cs b/src/NHibernate/Loader/JoinWalker.cs index 65d7594395c..e2650582718 100644 --- a/src/NHibernate/Loader/JoinWalker.cs +++ b/src/NHibernate/Loader/JoinWalker.cs @@ -375,6 +375,7 @@ private void WalkCollectionTree(IQueryableCollection persister, string alias, st } else if (type.IsComponentType) { + _joinQueue.Enqueue(NextLevelJoinQueueEntry.Instance); WalkCompositeElementTree( (IAbstractComponentType) type, persister.ElementColumnNames,