Skip to content

Commit 24b4544

Browse files
gliljasfredericDelaporte
authored andcommitted
Deep removal of Fetch result operators when Any is used (#1559)
1 parent f916c61 commit 24b4544

File tree

3 files changed

+74
-4
lines changed

3 files changed

+74
-4
lines changed

src/NHibernate.Test/Linq/ByMethod/AnyTests.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,26 @@ public void AnyWithCount()
5454
public void AnyWithFetch()
5555
{
5656
//NH-3241
57-
var result = db.Orders.Fetch(x => x.Customer).FetchMany(x => x.OrderLines).Any();
57+
Assert.DoesNotThrow(() =>
58+
{
59+
var result = db.Orders.Fetch(x => x.Customer).FetchMany(x => x.OrderLines).Any();
60+
}
61+
);
62+
}
63+
64+
[Test]
65+
public void AnyWithFetchInSubQuery()
66+
{
67+
Assert.DoesNotThrow(() =>
68+
{
69+
var result = db.Orders
70+
.Where(x => x.Customer.CustomerId == "Test")
71+
.Fetch(x => x.Customer)
72+
.FetchMany(x => x.OrderLines)
73+
.Where(x => x.Freight > 1)
74+
.Count();
75+
}
76+
);
5877
}
5978
}
6079
}

src/NHibernate/Linq/ReWriters/RemoveUnnecessaryBodyOperators.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ public override void VisitResultOperator(ResultOperatorBase resultOperator, Quer
3636
}
3737
if (resultOperator is AnyResultOperator)
3838
{
39-
Array.ForEach(queryModel.ResultOperators.OfType<FetchOneRequest>().ToArray(), op => queryModel.ResultOperators.Remove(op));
40-
Array.ForEach(queryModel.ResultOperators.OfType<FetchManyRequest>().ToArray(), op => queryModel.ResultOperators.Remove(op));
39+
ResultOperatorRemover.Remove(queryModel, x => x is FetchRequestBase);
4140
}
4241
base.VisitResultOperator(resultOperator, queryModel, index);
4342
}
4443
}
45-
}
44+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using NHibernate.Linq.Visitors;
3+
using Remotion.Linq;
4+
using Remotion.Linq.Clauses;
5+
using Remotion.Linq.Clauses.Expressions;
6+
7+
namespace NHibernate.Linq.ReWriters
8+
{
9+
public class ResultOperatorRemover : NhQueryModelVisitorBase
10+
{
11+
private readonly Func<ResultOperatorBase, bool> _predicate;
12+
13+
private ResultOperatorRemover(Func<ResultOperatorBase, bool> predicate)
14+
{
15+
_predicate = predicate;
16+
}
17+
18+
public static void Remove(QueryModel queryModel, Func<ResultOperatorBase, bool> predicate)
19+
{
20+
var rewriter = new ResultOperatorRemover(predicate);
21+
22+
rewriter.VisitQueryModel(queryModel);
23+
}
24+
25+
public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index)
26+
{
27+
if (_predicate(resultOperator))
28+
{
29+
queryModel.ResultOperators.Remove(resultOperator);
30+
return;
31+
}
32+
base.VisitResultOperator(resultOperator, queryModel, index);
33+
}
34+
35+
public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
36+
{
37+
var subQueryExpression = fromClause.FromExpression as SubQueryExpression;
38+
if (subQueryExpression != null)
39+
VisitQueryModel(subQueryExpression.QueryModel);
40+
base.VisitAdditionalFromClause(fromClause, queryModel, index);
41+
}
42+
43+
public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
44+
{
45+
var subQueryExpression = fromClause.FromExpression as SubQueryExpression;
46+
if (subQueryExpression != null)
47+
VisitQueryModel(subQueryExpression.QueryModel);
48+
base.VisitMainFromClause(fromClause, queryModel);
49+
}
50+
51+
}
52+
}

0 commit comments

Comments
 (0)