diff --git a/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs b/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs index 8dac8ed3a0d..a8aabd37b7e 100644 --- a/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs +++ b/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs @@ -549,6 +549,55 @@ public void GroupByComputedValueInObjectArray() Assert.AreEqual(830, orderGroups.Sum(g => g.Count)); } + [Test(Description = "NH-3801")] + public void GroupByComputedValueWithJoinOnObject() + { + var orderGroups = db.OrderLines.GroupBy(o => o.Order.Customer == null ? 0 : 1).Select(g => new { Key = g.Key, Count = g.Count() }).ToList(); + Assert.AreEqual(2155, orderGroups.Sum(g => g.Count)); + } + + [Test(Description = "NH-3801")] + public void GroupByComputedValueWithJoinOnId() + { + var orderGroups = db.OrderLines.GroupBy(o => o.Order.Customer.CustomerId == null ? 0 : 1).Select(g => new { Key = g.Key, Count = g.Count() }).ToList(); + Assert.AreEqual(2155, orderGroups.Sum(g => g.Count)); + } + + [Test(Description = "NH-3801")] + public void GroupByComputedValueInAnonymousTypeWithJoinOnObject() + { + var orderGroups = db.OrderLines.GroupBy(o => new { Key = o.Order.Customer == null ? 0 : 1 }).Select(g => new { Key = g.Key, Count = g.Count() }).ToList(); + Assert.AreEqual(2155, orderGroups.Sum(g => g.Count)); + } + + [Test(Description = "NH-3801")] + public void GroupByComputedValueInAnonymousTypeWithJoinOnId() + { + var orderGroups = db.OrderLines.GroupBy(o => new { Key = o.Order.Customer.CustomerId == null ? 0 : 1 }).Select(g => new { Key = g.Key, Count = g.Count() }).ToList(); + Assert.AreEqual(2155, orderGroups.Sum(g => g.Count)); + } + + [Test(Description = "NH-3801")] + public void GroupByComputedValueInObjectArrayWithJoinOnObject() + { + var orderGroups = db.OrderLines.GroupBy(o => new[] { o.Order.Customer == null ? 0 : 1 }).Select(g => new { Key = g.Key, Count = g.Count() }).ToList(); + Assert.AreEqual(2155, orderGroups.Sum(g => g.Count)); + } + + [Test(Description = "NH-3801")] + public void GroupByComputedValueInObjectArrayWithJoinOnId() + { + var orderGroups = db.OrderLines.GroupBy(o => new[] { o.Order.Customer.CustomerId == null ? 0 : 1 }).Select(g => new { Key = g.Key, Count = g.Count() }).ToList(); + Assert.AreEqual(2155, orderGroups.Sum(g => g.Count)); + } + + [Test(Description = "NH-3801")] + public void GroupByComputedValueInObjectArrayWithJoinInRightSideOfCase() + { + var orderGroups = db.OrderLines.GroupBy(o => new[] { o.Order.Customer.CustomerId == null ? "unknown" : o.Order.Customer.CompanyName }).Select(g => new { Key = g.Key, Count = g.Count() }).ToList(); + Assert.AreEqual(2155, orderGroups.Sum(g => g.Count)); + } + private static void CheckGrouping(IEnumerable> groupedItems, Func groupBy) { var used = new HashSet(); diff --git a/src/NHibernate.Test/Linq/JoinTests.cs b/src/NHibernate.Test/Linq/JoinTests.cs index 493247df242..dc6fd0dced4 100644 --- a/src/NHibernate.Test/Linq/JoinTests.cs +++ b/src/NHibernate.Test/Linq/JoinTests.cs @@ -260,6 +260,58 @@ public void OrderLinesWithSelectingOrderIdAndDateShouldProduceOneJoin() } } + [Test(Description = "NH-3801")] + public void OrderLinesWithSelectingCustomerIdInCaseShouldProduceOneJoin() + { + using (var spy = new SqlLogSpy()) + { + (from l in db.OrderLines + select new { CustomerKnown = l.Order.Customer.CustomerId == null ? 0 : 1, l.Order.OrderDate }).ToList(); + + var countJoins = CountJoins(spy); + Assert.That(countJoins, Is.EqualTo(1)); + } + } + + [Test(Description = "NH-3801")] + public void OrderLinesWithSelectingCustomerInCaseShouldProduceOneJoin() + { + using (var spy = new SqlLogSpy()) + { + (from l in db.OrderLines + select new { CustomerKnown = l.Order.Customer == null ? 0 : 1, l.Order.OrderDate }).ToList(); + + var countJoins = CountJoins(spy); + Assert.That(countJoins, Is.EqualTo(1)); + } + } + + [Test(Description = "NH-3801")] + public void OrderLinesWithSelectingCustomerNameInCaseShouldProduceTwoJoins() + { + using (var spy = new SqlLogSpy()) + { + (from l in db.OrderLines + select new { CustomerKnown = l.Order.Customer.CustomerId == null ? "unknown" : l.Order.Customer.CompanyName, l.Order.OrderDate }).ToList(); + + var countJoins = CountJoins(spy); + Assert.That(countJoins, Is.EqualTo(2)); + } + } + + [Test(Description = "NH-3801")] + public void OrderLinesWithSelectingCustomerNameInCaseShouldProduceTwoJoinsAlternate() + { + using (var spy = new SqlLogSpy()) + { + (from l in db.OrderLines + select new { CustomerKnown = l.Order.Customer == null ? "unknown" : l.Order.Customer.CompanyName, l.Order.OrderDate }).ToList(); + + var countJoins = CountJoins(spy); + Assert.That(countJoins, Is.EqualTo(2)); + } + } + private static int CountJoins(LogSpy sqlLog) { return Count(sqlLog, "join"); diff --git a/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs b/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs index d92487d31f0..a465ad46823 100644 --- a/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs +++ b/src/NHibernate/Hql/Ast/ANTLR/Tree/DotNode.cs @@ -407,7 +407,7 @@ private void DereferenceEntity(EntityType entityType, bool implicitJoin, string } else { - joinIsNeeded = generateJoin || ( Walker.IsInSelect || Walker.IsInFrom ); + joinIsNeeded = generateJoin || ( (Walker.IsInSelect && !Walker.IsInCase ) || Walker.IsInFrom ); } if ( joinIsNeeded ) diff --git a/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs b/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs index 795edf52dc5..3c3bf5e0d71 100644 --- a/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs +++ b/src/NHibernate/Linq/GroupBy/AggregatingGroupByRewriter.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; using NHibernate.Linq.Clauses; using NHibernate.Linq.ReWriters; using NHibernate.Linq.Visitors; -using NHibernate.Util; using Remotion.Linq; using Remotion.Linq.Clauses.Expressions; using Remotion.Linq.Clauses.ResultOperators; @@ -44,7 +42,7 @@ public static class AggregatingGroupByRewriter typeof (CacheableResultOperator) }; - public static void ReWrite(QueryModel queryModel, IList groupByKeys) + public static void ReWrite(QueryModel queryModel) { var subQueryExpression = queryModel.MainFromClause.FromExpression as SubQueryExpression; @@ -59,7 +57,6 @@ public static void ReWrite(QueryModel queryModel, IList groupByKeys) var groupBy = operators[0] as GroupResultOperator; if (groupBy != null) { - groupBy.ExtractKeyExpressions(groupByKeys); FlattenSubQuery(queryModel, subQueryExpression.QueryModel, groupBy); } } diff --git a/src/NHibernate/Linq/GroupResultOperatorExtensions.cs b/src/NHibernate/Linq/GroupResultOperatorExtensions.cs deleted file mode 100644 index 2a6ee7d42c3..00000000000 --- a/src/NHibernate/Linq/GroupResultOperatorExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using NHibernate.Util; -using Remotion.Linq.Clauses.ResultOperators; - -namespace NHibernate.Linq -{ - internal static class GroupResultOperatorExtensions - { - public static void ExtractKeyExpressions(this GroupResultOperator groupResult, IList groupByKeys) - { - if (groupResult.KeySelector is NewExpression) - (groupResult.KeySelector as NewExpression).Arguments.ForEach(groupByKeys.Add); - else if (groupResult.KeySelector is NewArrayExpression) - (groupResult.KeySelector as NewArrayExpression).Expressions.ForEach(groupByKeys.Add); - else - groupByKeys.Add(groupResult.KeySelector); - } - } -} diff --git a/src/NHibernate/Linq/ReWriters/AddJoinsReWriter.cs b/src/NHibernate/Linq/ReWriters/AddJoinsReWriter.cs index 6fa4650280c..0dc17e068b1 100644 --- a/src/NHibernate/Linq/ReWriters/AddJoinsReWriter.cs +++ b/src/NHibernate/Linq/ReWriters/AddJoinsReWriter.cs @@ -15,37 +15,36 @@ internal interface IIsEntityDecider public class AddJoinsReWriter : QueryModelVisitorBase, IIsEntityDecider { private readonly ISessionFactoryImplementor _sessionFactory; - private readonly SelectJoinDetector _selectJoinDetector; - private readonly ResultOperatorAndOrderByJoinDetector _resultOperatorAndOrderByJoinDetector; + private readonly MemberExpressionJoinDetector _memberExpressionJoinDetector; private readonly WhereJoinDetector _whereJoinDetector; private AddJoinsReWriter(ISessionFactoryImplementor sessionFactory, QueryModel queryModel) { _sessionFactory = sessionFactory; var joiner = new Joiner(queryModel); - _selectJoinDetector = new SelectJoinDetector(this, joiner); - _resultOperatorAndOrderByJoinDetector = new ResultOperatorAndOrderByJoinDetector(this, joiner); + _memberExpressionJoinDetector = new MemberExpressionJoinDetector(this, joiner); _whereJoinDetector = new WhereJoinDetector(this, joiner); } - public static void ReWrite(QueryModel queryModel, ISessionFactoryImplementor sessionFactory) + public static void ReWrite(QueryModel queryModel, VisitorParameters parameters) { - new AddJoinsReWriter(sessionFactory, queryModel).VisitQueryModel(queryModel); + var visitor = new AddJoinsReWriter(parameters.SessionFactory, queryModel); + visitor.VisitQueryModel(queryModel); } public override void VisitSelectClause(SelectClause selectClause, QueryModel queryModel) { - _selectJoinDetector.Transform(selectClause); + _memberExpressionJoinDetector.Transform(selectClause); } public override void VisitOrdering(Ordering ordering, QueryModel queryModel, OrderByClause orderByClause, int index) { - _resultOperatorAndOrderByJoinDetector.Transform(ordering); + _memberExpressionJoinDetector.Transform(ordering); } public override void VisitResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, int index) { - _resultOperatorAndOrderByJoinDetector.Transform(resultOperator); + _memberExpressionJoinDetector.Transform(resultOperator); } public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index) diff --git a/src/NHibernate/Linq/Visitors/JoinBuilder.cs b/src/NHibernate/Linq/Visitors/JoinBuilder.cs index f8952d399f6..f41ccea5022 100644 --- a/src/NHibernate/Linq/Visitors/JoinBuilder.cs +++ b/src/NHibernate/Linq/Visitors/JoinBuilder.cs @@ -60,14 +60,14 @@ public void MakeInnerIfJoined(string key) public bool CanAddJoin(Expression expression) { var source = QuerySourceExtractor.GetQuerySource(expression); - - if (_queryModel.MainFromClause == source) + + if (_queryModel.MainFromClause == source) return true; - + var bodyClause = source as IBodyClause; - if (bodyClause != null && _queryModel.BodyClauses.Contains(bodyClause)) + if (bodyClause != null && _queryModel.BodyClauses.Contains(bodyClause)) return true; - + var resultOperatorBase = source as ResultOperatorBase; return resultOperatorBase != null && _queryModel.ResultOperators.Contains(resultOperatorBase); } diff --git a/src/NHibernate/Linq/Visitors/MemberExpressionJoinDetector.cs b/src/NHibernate/Linq/Visitors/MemberExpressionJoinDetector.cs new file mode 100644 index 00000000000..f2e5d4b474d --- /dev/null +++ b/src/NHibernate/Linq/Visitors/MemberExpressionJoinDetector.cs @@ -0,0 +1,91 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq.Expressions; +using NHibernate.Linq.ReWriters; +using Remotion.Linq.Clauses; +using Remotion.Linq.Clauses.Expressions; +using Remotion.Linq.Parsing; + +namespace NHibernate.Linq.Visitors +{ + /// + /// Detects joins in Select, OrderBy and Results (GroupBy) clauses. + /// Replaces them with appropriate joins, maintaining reference equality between different clauses. + /// This allows extracted GroupBy key expression to also be replaced so that they can continue to match replaced Select expressions + /// + internal class MemberExpressionJoinDetector : ExpressionTreeVisitor + { + private readonly IIsEntityDecider _isEntityDecider; + private readonly IJoiner _joiner; + + private bool _requiresJoinForNonIdentifier; + private bool _hasIdentifier; + private int _memberExpressionDepth; + + public MemberExpressionJoinDetector(IIsEntityDecider isEntityDecider, IJoiner joiner) + { + _isEntityDecider = isEntityDecider; + _joiner = joiner; + } + + protected override Expression VisitMemberExpression(MemberExpression expression) + { + var isIdentifier = _isEntityDecider.IsIdentifier(expression.Expression.Type, expression.Member.Name); + if (isIdentifier) + _hasIdentifier = true; + if (!isIdentifier) + _memberExpressionDepth++; + + var result = base.VisitMemberExpression(expression); + + if (!isIdentifier) + _memberExpressionDepth--; + + if (_isEntityDecider.IsEntity(expression.Type) && + ((_requiresJoinForNonIdentifier && !_hasIdentifier) || _memberExpressionDepth > 0) && + _joiner.CanAddJoin(expression)) + { + var key = ExpressionKeyVisitor.Visit(expression, null); + return _joiner.AddJoin(result, key); + } + + return result; + } + + protected override Expression VisitSubQueryExpression(SubQueryExpression expression) + { + expression.QueryModel.TransformExpressions(VisitExpression); + return expression; + } + + protected override Expression VisitConditionalExpression(ConditionalExpression expression) + { + var oldRequiresJoinForNonIdentifier = _requiresJoinForNonIdentifier; + _requiresJoinForNonIdentifier = false; + var newTest = VisitExpression(expression.Test); + _requiresJoinForNonIdentifier = oldRequiresJoinForNonIdentifier; + var newFalse = VisitExpression(expression.IfFalse); + var newTrue = VisitExpression(expression.IfTrue); + if ((newTest != expression.Test) || (newFalse != expression.IfFalse) || (newTrue != expression.IfTrue)) + return Expression.Condition(newTest, newTrue, newFalse); + return expression; + } + + public void Transform(SelectClause selectClause) + { + _requiresJoinForNonIdentifier = true; + selectClause.TransformExpressions(VisitExpression); + _requiresJoinForNonIdentifier = false; + } + + public void Transform(ResultOperatorBase resultOperator) + { + resultOperator.TransformExpressions(VisitExpression); + } + + public void Transform(Ordering ordering) + { + ordering.TransformExpressions(VisitExpression); + } + } +} \ No newline at end of file diff --git a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs index 63361bb55a6..a83d3911684 100644 --- a/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs +++ b/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs @@ -34,7 +34,7 @@ public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel quer NonAggregatingGroupByRewriter.ReWrite(queryModel); // Rewrite aggregate group-by statements - AggregatingGroupByRewriter.ReWrite(queryModel, parameters.GroupByKeys); + AggregatingGroupByRewriter.ReWrite(queryModel); // Rewrite aggregating group-joins AggregatingGroupJoinRewriter.ReWrite(queryModel); @@ -57,7 +57,7 @@ public static ExpressionToHqlTranslationResults GenerateHqlQuery(QueryModel quer ArrayIndexExpressionFlattener.ReWrite(queryModel); // Add joins for references - AddJoinsReWriter.ReWrite(queryModel, parameters.SessionFactory); + AddJoinsReWriter.ReWrite(queryModel, parameters); // Move OrderBy clauses to end MoveOrderByToEndRewriter.ReWrite(queryModel); @@ -238,7 +238,7 @@ public override void VisitSelectClause(SelectClause selectClause, QueryModel que { CurrentEvaluationType = selectClause.GetOutputDataInfo(); - var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters, VisitorParameters.GroupByKeys); + var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters); visitor.Visit(selectClause.Selector); diff --git a/src/NHibernate/Linq/Visitors/ResultOperatorAndOrderByJoinDetector.cs b/src/NHibernate/Linq/Visitors/ResultOperatorAndOrderByJoinDetector.cs deleted file mode 100644 index 72471d96dff..00000000000 --- a/src/NHibernate/Linq/Visitors/ResultOperatorAndOrderByJoinDetector.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Linq.Expressions; -using NHibernate.Linq.ReWriters; -using Remotion.Linq.Clauses; -using Remotion.Linq.Clauses.Expressions; -using Remotion.Linq.Parsing; - -namespace NHibernate.Linq.Visitors -{ - internal class ResultOperatorAndOrderByJoinDetector : ExpressionTreeVisitor - { - private readonly IIsEntityDecider _isEntityDecider; - private readonly IJoiner _joiner; - private int _memberExpressionDepth; - - public ResultOperatorAndOrderByJoinDetector(IIsEntityDecider isEntityDecider, IJoiner joiner) - { - _isEntityDecider = isEntityDecider; - _joiner = joiner; - } - - protected override Expression VisitMemberExpression(MemberExpression expression) - { - var isIdentifier = _isEntityDecider.IsIdentifier(expression.Expression.Type, expression.Member.Name); - if (!isIdentifier) - _memberExpressionDepth++; - - var result = base.VisitMemberExpression(expression); - - if (!isIdentifier) - _memberExpressionDepth--; - - if (_isEntityDecider.IsEntity(expression.Type) && - _memberExpressionDepth > 0 && - _joiner.CanAddJoin(expression)) - { - var key = ExpressionKeyVisitor.Visit(expression, null); - return _joiner.AddJoin(result, key); - } - - return result; - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - expression.QueryModel.TransformExpressions(VisitExpression); - return expression; - } - - public void Transform(ResultOperatorBase resultOperator) - { - resultOperator.TransformExpressions(VisitExpression); - } - - public void Transform(Ordering ordering) - { - ordering.TransformExpressions(VisitExpression); - } - } -} \ No newline at end of file diff --git a/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs b/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs index a026db89659..0d3d5d6a14e 100644 --- a/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs +++ b/src/NHibernate/Linq/Visitors/SelectClauseNominator.cs @@ -64,6 +64,12 @@ public override Expression VisitExpression(Expression expression) ContainsUntranslatedMethodCalls = ContainsUntranslatedMethodCalls || !isRegisteredFunction; } + // Attempt to project conditionals to the DB to prevent inner joins, or more projection work on result than is needed + if (expression != null && expression.NodeType == ExpressionType.Conditional) + { + projectConstantsInHql = true; + } + _stateStack.Push(projectConstantsInHql); if (expression == null) diff --git a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs index 73d2eaedf15..2692fb7ed43 100644 --- a/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs +++ b/src/NHibernate/Linq/Visitors/SelectClauseVisitor.cs @@ -18,12 +18,11 @@ public class SelectClauseVisitor : ExpressionTreeVisitor private List _hqlTreeNodes = new List(); private readonly HqlGeneratorExpressionTreeVisitor _hqlVisitor; - public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters, IEnumerable groupByKeys) + public SelectClauseVisitor(System.Type inputType, VisitorParameters parameters) { _inputParameter = Expression.Parameter(inputType, "input"); _parameters = parameters; _hqlVisitor = new HqlGeneratorExpressionTreeVisitor(_parameters); - _hqlNodes = new HashSet(groupByKeys); } public LambdaExpression ProjectionExpression { get; private set; } @@ -44,7 +43,7 @@ public void Visit(Expression expression) // Find the sub trees that can be expressed purely in HQL var nominator = new SelectClauseHqlNominator(_parameters); nominator.Visit(expression); - _hqlNodes.UnionWith(nominator.HqlCandidates); + _hqlNodes = nominator.HqlCandidates; // Linq2SQL ignores calls to local methods. Linq2EF seems to not support // calls to local methods at all. For NHibernate we support local methods, diff --git a/src/NHibernate/Linq/Visitors/SelectJoinDetector.cs b/src/NHibernate/Linq/Visitors/SelectJoinDetector.cs deleted file mode 100644 index c281d3814c8..00000000000 --- a/src/NHibernate/Linq/Visitors/SelectJoinDetector.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Linq.Expressions; -using NHibernate.Linq.ReWriters; -using Remotion.Linq.Clauses; -using Remotion.Linq.Clauses.Expressions; -using Remotion.Linq.Parsing; - -namespace NHibernate.Linq.Visitors -{ - internal class SelectJoinDetector : ExpressionTreeVisitor - { - private readonly IIsEntityDecider _isEntityDecider; - private readonly IJoiner _joiner; - private bool _hasIdentifier; - private int _identifierMemberExpressionDepth; - - public SelectJoinDetector(IIsEntityDecider isEntityDecider, IJoiner joiner) - { - _isEntityDecider = isEntityDecider; - _joiner = joiner; - } - - public void Transform(SelectClause selectClause) - { - selectClause.TransformExpressions(VisitExpression); - } - - protected override Expression VisitMemberExpression(MemberExpression expression) - { - if (_isEntityDecider.IsIdentifier(expression.Expression.Type, expression.Member.Name)) - _hasIdentifier = true; - else if (_hasIdentifier) - _identifierMemberExpressionDepth++; - - var result = base.VisitMemberExpression(expression); - if (_hasIdentifier) - _identifierMemberExpressionDepth--; - - if (_isEntityDecider.IsEntity(expression.Type) && - (!_hasIdentifier || _identifierMemberExpressionDepth > 0) && - _joiner.CanAddJoin(expression)) - { - var key = ExpressionKeyVisitor.Visit(expression, null); - return _joiner.AddJoin(result, key); - } - - _hasIdentifier = false; - - return result; - } - - protected override Expression VisitSubQueryExpression(SubQueryExpression expression) - { - expression.QueryModel.TransformExpressions(VisitExpression); - return expression; - } - } -} diff --git a/src/NHibernate/Linq/Visitors/VisitorParameters.cs b/src/NHibernate/Linq/Visitors/VisitorParameters.cs index 03aba50ea8d..27ef5de7029 100644 --- a/src/NHibernate/Linq/Visitors/VisitorParameters.cs +++ b/src/NHibernate/Linq/Visitors/VisitorParameters.cs @@ -16,8 +16,6 @@ public class VisitorParameters public QuerySourceNamer QuerySourceNamer { get; set; } - public IList GroupByKeys { get; private set; } - public VisitorParameters( ISessionFactoryImplementor sessionFactory, IDictionary constantToParameterMap, @@ -28,7 +26,6 @@ public VisitorParameters( ConstantToParameterMap = constantToParameterMap; RequiredHqlParameters = requiredHqlParameters; QuerySourceNamer = querySourceNamer; - GroupByKeys = new List(); } } } \ No newline at end of file diff --git a/src/NHibernate/NHibernate.csproj b/src/NHibernate/NHibernate.csproj index 1d72824530d..020a5fca917 100644 --- a/src/NHibernate/NHibernate.csproj +++ b/src/NHibernate/NHibernate.csproj @@ -299,7 +299,6 @@ - @@ -323,11 +322,10 @@ - + -