|
1 | 1 | using System.Collections.Generic;
|
2 | 2 | using System.Dynamic;
|
| 3 | +using System.Linq; |
3 | 4 | using System.Linq.Expressions;
|
4 | 5 | using NHibernate.Engine;
|
5 | 6 | using NHibernate.Param;
|
6 | 7 | using NHibernate.Type;
|
7 | 8 | using NHibernate.Util;
|
8 | 9 | using Remotion.Linq;
|
| 10 | +using Remotion.Linq.Clauses; |
9 | 11 | using Remotion.Linq.Clauses.Expressions;
|
| 12 | +using Remotion.Linq.Clauses.ResultOperators; |
10 | 13 | using Remotion.Linq.Parsing;
|
11 | 14 |
|
12 | 15 | namespace NHibernate.Linq.Visitors
|
@@ -219,14 +222,35 @@ protected override Expression VisitConstant(ConstantExpression node)
|
219 | 222 | return node;
|
220 | 223 | }
|
221 | 224 |
|
222 |
| - public override Expression Visit(Expression node) |
| 225 | + protected override Expression VisitSubQuery(SubQueryExpression node) |
223 | 226 | {
|
224 |
| - if (node is SubQueryExpression subQueryExpression) |
| 227 | + // ReLinq wraps all ResultOperatorExpressionNodeBase into a SubQueryExpression. In case of |
| 228 | + // ContainsResultOperator where the constant expression is dislocated from the related expression, |
| 229 | + // we have to manually link the related expressions. |
| 230 | + if (node.QueryModel.ResultOperators.Count == 1 && |
| 231 | + node.QueryModel.ResultOperators[0] is ContainsResultOperator containsOperator && |
| 232 | + node.QueryModel.SelectClause.Selector is QuerySourceReferenceExpression querySourceReference && |
| 233 | + querySourceReference.ReferencedQuerySource is MainFromClause mainFromClause && |
| 234 | + mainFromClause.FromExpression is ConstantExpression constantExpression) |
225 | 235 | {
|
226 |
| - subQueryExpression.QueryModel.TransformExpressions(Visit); |
| 236 | + VisitConstant(constantExpression); |
| 237 | + AddRelatedExpression(constantExpression, Unwrap(Visit(containsOperator.Item))); |
| 238 | + // Copy all found MemberExpressions to the constant expression |
| 239 | + // (e.g. values.Contains(o.Name != o.Name2 ? o.Enum1 : o.Enum2) -> copy o.Enum1 and o.Enum2) |
| 240 | + if (RelatedExpressions.TryGetValue(containsOperator.Item, out var set)) |
| 241 | + { |
| 242 | + foreach (var nestedMemberExpression in set) |
| 243 | + { |
| 244 | + AddRelatedExpression(constantExpression, nestedMemberExpression); |
| 245 | + } |
| 246 | + } |
| 247 | + } |
| 248 | + else |
| 249 | + { |
| 250 | + node.QueryModel.TransformExpressions(Visit); |
227 | 251 | }
|
228 | 252 |
|
229 |
| - return base.Visit(node); |
| 253 | + return node; |
230 | 254 | }
|
231 | 255 |
|
232 | 256 | private void VisitAssign(Expression leftNode, Expression rightNode)
|
|
0 commit comments