diff --git a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs index 43720cb12f..3eb720c871 100644 --- a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs +++ b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs @@ -111,6 +111,7 @@ public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel quer } private readonly IntermediateHqlTree _hqlTree; + private readonly HashSet _hqlCandidates; private readonly NhLinqExpressionReturnType? _rootReturnType; private static readonly ResultOperatorMap ResultOperatorMap; private bool _serverSide = true; @@ -165,6 +166,7 @@ private QueryModelVisitor(VisitorParameters visitorParameters, bool root, QueryM _root = root; _rootReturnType = root ? rootReturnType : null; _hqlTree = new IntermediateHqlTree(root, _queryMode); + _hqlCandidates = new HashSet(); } private void Visit() @@ -476,7 +478,7 @@ public override void VisitSelectClause(SelectClause selectClause, QueryModel que private HqlSelect GetSelectClause(Expression selectClause) { - var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters); + var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters, _hqlCandidates); visitor.VisitSelector(selectClause, !_root); @@ -537,7 +539,7 @@ private void VisitDeleteClause(Expression expression) return; // We only need to check there is no unexpected select, for avoiding silently ignoring them. - var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters); + var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters, new HashSet()); visitor.VisitSelector(expression); if (visitor.ProjectionExpression != null) @@ -566,6 +568,7 @@ public override void VisitOrderByClause(OrderByClause orderByClause, QueryModel : (HqlDirectionStatement)_hqlTree.TreeBuilder.Descending(); _hqlTree.AddOrderByClause(orderBy, direction); + _hqlCandidates.Add(clause.Expression); } } diff --git a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs index a5155415df..9f73e293e4 100644 --- a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs +++ b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs @@ -16,14 +16,22 @@ public class SelectClauseVisitor : RelinqExpressionVisitor private HashSet _hqlNodes; private readonly ParameterExpression _inputParameter; private readonly VisitorParameters _parameters; + private readonly HashSet _hqlCandidates; private int _iColumn; private List _hqlTreeNodes = new List(); private readonly HqlGeneratorExpressionVisitor _hqlVisitor; - public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters) + // Since v5.6 + [Obsolete("Use overload providing expressions to be executed with HQL.")] + public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters) : + this(inputType, parameters, new HashSet()) + { } + + public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters, HashSet hqlCandidates) { _inputParameter = Expression.Parameter(inputType, "input"); _parameters = parameters; + _hqlCandidates = hqlCandidates; _hqlVisitor = new HqlGeneratorExpressionVisitor(_parameters); } @@ -69,9 +77,9 @@ public void VisitSelector(Expression expression, bool isSubQuery) if (distinct != null) { - var treeNodes = new List(_hqlTreeNodes.Count + 1) {_hqlTreeBuilder.Distinct()}; + var treeNodes = new List(_hqlTreeNodes.Count + 1) { _hqlTreeBuilder.Distinct() }; treeNodes.AddRange(_hqlTreeNodes); - _hqlTreeNodes = new List(1) {_hqlTreeBuilder.ExpressionSubTreeHolder(treeNodes)}; + _hqlTreeNodes = new List(1) { _hqlTreeBuilder.ExpressionSubTreeHolder(treeNodes) }; } } @@ -82,7 +90,7 @@ public override Expression Visit(Expression expression) return null; } - if (_hqlNodes.Contains(expression)) + if (_hqlNodes.Contains(expression) || _hqlCandidates.Contains(expression)) { // Pure HQL evaluation _hqlTreeNodes.Add(_hqlVisitor.Visit(expression).AsExpression());