From 09b1d43890b408cccd1f3c27d49788c35fd57df9 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Wed, 2 Aug 2023 10:24:36 +0300 Subject: [PATCH 1/3] Test case --- .../FetchLazyPropertiesFixture.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/NHibernate.Test/FetchLazyProperties/FetchLazyPropertiesFixture.cs b/src/NHibernate.Test/FetchLazyProperties/FetchLazyPropertiesFixture.cs index 7a89e998c36..f05c462e5c8 100644 --- a/src/NHibernate.Test/FetchLazyProperties/FetchLazyPropertiesFixture.cs +++ b/src/NHibernate.Test/FetchLazyProperties/FetchLazyPropertiesFixture.cs @@ -175,6 +175,18 @@ public void TestLinqFetchProperty() AssertFetchProperty(person); } + [Test] + public void TestLinqFetchPropertyAfterSelect() + { + using var s = OpenSession(); + var owner = s.Query() + .Select(a => a.Owner) + .Fetch(o => o.Image) + .FirstOrDefault(o => o.Id == 1); + + AssertFetchProperty(owner); + } + private static void AssertFetchProperty(Person person) { Assert.That(person, Is.Not.Null); From 72bb8c3c7f71347914e4df091df09a6ab4469f1f Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Wed, 2 Aug 2023 10:25:50 +0300 Subject: [PATCH 2/3] Fix --- src/NHibernate/Linq/IntermediateHqlTree.cs | 11 +++++++++++ .../ResultOperatorProcessors/ProcessFetch.cs | 13 +++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/NHibernate/Linq/IntermediateHqlTree.cs b/src/NHibernate/Linq/IntermediateHqlTree.cs index 17417319e41..4104ff4854d 100644 --- a/src/NHibernate/Linq/IntermediateHqlTree.cs +++ b/src/NHibernate/Linq/IntermediateHqlTree.cs @@ -127,6 +127,17 @@ public void AddFromClause(HqlTreeNode from) _root.NodesPreOrder.OfType().First().AddChild(from); } + internal HqlTreeNode GetFromNodeByAlias(string alias) => + _root.NodesPreOrder + .First(x => x.AstNode.Type == HqlSqlWalker.FROM).Children + .First(x => GetNodeAlias(x) == alias); + + private static string GetNodeAlias(HqlTreeNode fromNode) => + fromNode.Children + .Select(x => x.AstNode) + .First(x => x.Type == HqlSqlWalker.ALIAS) + .Text; + internal HqlRange GetFromRangeClause() { return _root.NodesPreOrder.OfType().First().Children.OfType().FirstOrDefault(); diff --git a/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs b/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs index 7c18f9476f4..69323f0a006 100644 --- a/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs +++ b/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessFetch.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using NHibernate.Hql.Ast; +using NHibernate.Hql.Ast.ANTLR; using NHibernate.Persister.Entity; using NHibernate.Type; using Remotion.Linq.EagerFetching; @@ -21,7 +22,7 @@ public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryMode public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias) { - Process(resultOperator, queryModelVisitor, tree, null, sourceAlias); + Process(resultOperator, queryModelVisitor, tree, tree.GetFromNodeByAlias(sourceAlias), sourceAlias); } private void Process( @@ -68,13 +69,12 @@ private void Process( propType = metadata.GetPropertyType(resultOperator.RelationMember.Name); } } - + if (propType != null && !propType.IsAssociationType) { if (currentNode == null) { - currentNode = tree.GetFromRangeClause() - ?? throw new InvalidOperationException($"Property {resultOperator.RelationMember.Name} cannot be fetched for this type of query."); + throw new InvalidOperationException($"Property {resultOperator.RelationMember.Name} cannot be fetched for this type of query."); } currentNode.AddChild(tree.TreeBuilder.Fetch()); @@ -85,12 +85,13 @@ private void Process( { if (componentType == null) { - componentType = propType as ComponentType; - if (componentType == null) + if (!propType.IsComponentType) { throw new InvalidOperationException( $"Property {innerFetch.RelationMember.Name} cannot be fetched from a non component type property {resultOperator.RelationMember.Name}."); } + + componentType = (ComponentType) propType; } var subTypeIndex = componentType.GetPropertyIndex(innerFetch.RelationMember.Name); From eea253ffcbd378179adf3aa5c7c35196fa43e332 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 3 Aug 2023 09:52:57 +0000 Subject: [PATCH 3/3] Generate async files --- .../FetchLazyPropertiesFixture.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/NHibernate.Test/Async/FetchLazyProperties/FetchLazyPropertiesFixture.cs b/src/NHibernate.Test/Async/FetchLazyProperties/FetchLazyPropertiesFixture.cs index 6a812cd5888..18df844bd71 100644 --- a/src/NHibernate.Test/Async/FetchLazyProperties/FetchLazyPropertiesFixture.cs +++ b/src/NHibernate.Test/Async/FetchLazyProperties/FetchLazyPropertiesFixture.cs @@ -186,6 +186,18 @@ public async Task TestLinqFetchPropertyAsync() AssertFetchProperty(person); } + [Test] + public async Task TestLinqFetchPropertyAfterSelectAsync() + { + using var s = OpenSession(); + var owner = await (s.Query() + .Select(a => a.Owner) + .Fetch(o => o.Image) + .FirstOrDefaultAsync(o => o.Id == 1)); + + AssertFetchProperty(owner); + } + private static void AssertFetchProperty(Person person) { Assert.That(person, Is.Not.Null);