Skip to content

Commit 8994076

Browse files
NH-3850 - Fix for polymorphic Linq query results aggregators failures.
1 parent e6fe73e commit 8994076

13 files changed

+299
-89
lines changed

src/NHibernate/Linq/EnumerableHelper.cs

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@ public static MemberInfo GetProperty<TSource, TResult>(Expression<Func<TSource,
6565
return ReflectHelper.GetProperty(property);
6666
}
6767
}
68-
68+
6969
[Obsolete("Please use NHibernate.Util.ReflectHelper instead")]
7070
public static class EnumerableHelper
7171
{
7272
public static MethodInfo GetMethod(string name, System.Type[] parameterTypes)
7373
{
7474
return typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
7575
.Where(m => m.Name == name &&
76-
ParameterTypesMatch(m.GetParameters(), parameterTypes))
76+
ReflectHelper.ParameterTypesMatch(m.GetParameters(), parameterTypes))
7777
.Single();
7878
}
7979

@@ -83,35 +83,9 @@ public static MethodInfo GetMethod(string name, System.Type[] parameterTypes, Sy
8383
.Where(m => m.Name == name &&
8484
m.ContainsGenericParameters &&
8585
m.GetGenericArguments().Count() == genericTypeParameters.Length &&
86-
ParameterTypesMatch(m.GetParameters(), parameterTypes))
86+
ReflectHelper.ParameterTypesMatch(m.GetParameters(), parameterTypes))
8787
.Single()
8888
.MakeGenericMethod(genericTypeParameters);
8989
}
90-
91-
private static bool ParameterTypesMatch(ParameterInfo[] parameters, System.Type[] types)
92-
{
93-
if (parameters.Length != types.Length)
94-
{
95-
return false;
96-
}
97-
98-
for (int i = 0; i < parameters.Length; i++)
99-
{
100-
if (parameters[i].ParameterType == types[i])
101-
{
102-
continue;
103-
}
104-
105-
if (parameters[i].ParameterType.ContainsGenericParameters && types[i].ContainsGenericParameters &&
106-
parameters[i].ParameterType.GetGenericArguments().Length == types[i].GetGenericArguments().Length)
107-
{
108-
continue;
109-
}
110-
111-
return false;
112-
}
113-
114-
return true;
115-
}
11690
}
11791
}

src/NHibernate/Linq/ExpressionToHqlTranslationResults.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Collections.ObjectModel;
4-
using System.Linq;
53
using System.Linq.Expressions;
6-
using System.Reflection;
74
using NHibernate.Hql.Ast;
85
using NHibernate.Type;
96

107
namespace NHibernate.Linq
118
{
129
public class ExpressionToHqlTranslationResults
1310
{
14-
public HqlTreeNode Statement { get; private set; }
15-
public ResultTransformer ResultTransformer { get; private set; }
16-
public Delegate PostExecuteTransformer { get; private set; }
17-
public List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>> AdditionalCriteria { get; private set; }
11+
public HqlTreeNode Statement { get; }
12+
public ResultTransformer ResultTransformer { get; }
13+
public Delegate PostExecuteTransformer { get; }
14+
public List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>> AdditionalCriteria { get; }
15+
16+
/// <summary>
17+
/// If execute result type does not match expected final result type (implying a post execute transformer
18+
/// will yield expected result type), the intermediate execute type.
19+
/// </summary>
20+
public System.Type ExecuteResultTypeOverride { get; }
1821

1922
public ExpressionToHqlTranslationResults(HqlTreeNode statement,
2023
IList<LambdaExpression> itemTransformers,
2124
IList<LambdaExpression> listTransformers,
2225
IList<LambdaExpression> postExecuteTransformers,
23-
List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>> additionalCriteria)
26+
List<Action<IQuery, IDictionary<string, Tuple<object, IType>>>> additionalCriteria,
27+
System.Type executeResultTypeOverride)
2428
{
2529
Statement = statement;
2630

@@ -35,6 +39,7 @@ public ExpressionToHqlTranslationResults(HqlTreeNode statement,
3539
}
3640

3741
AdditionalCriteria = additionalCriteria;
42+
ExecuteResultTypeOverride = executeResultTypeOverride;
3843
}
3944

4045
private static TDelegate MergeLambdasAndCompile<TDelegate>(IList<LambdaExpression> itemTransformers)

src/NHibernate/Linq/Functions/QueryableGenerator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ public class AllHqlGenerator : BaseHqlGeneratorForMethod
5353
public AllHqlGenerator()
5454
{
5555
SupportedMethods = new[]
56-
{
57-
ReflectHelper.GetMethodDefinition(() => Queryable.All<object>(null, null)),
58-
ReflectHelper.GetMethodDefinition(() => Enumerable.All<object>(null, null))
59-
};
56+
{
57+
ReflectHelper.GetMethodDefinition(() => Queryable.All<object>(null, null)),
58+
ReflectHelper.GetMethodDefinition(() => Enumerable.All<object>(null, null))
59+
};
6060
}
6161

6262
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)

src/NHibernate/Linq/IntermediateHqlTree.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ public HqlTreeNode Root
5050
}
5151
}
5252

53-
public HqlTreeBuilder TreeBuilder { get; private set; }
53+
/// <summary>
54+
/// If execute result type does not match expected final result type (implying a post execute transformer
55+
/// will yield expected result type), the intermediate execute type.
56+
/// </summary>
57+
public System.Type ExecuteResultTypeOverride { get; set; }
58+
59+
public HqlTreeBuilder TreeBuilder { get; }
5460

5561
public IntermediateHqlTree(bool root)
5662
{
@@ -62,10 +68,11 @@ public IntermediateHqlTree(bool root)
6268
public ExpressionToHqlTranslationResults GetTranslation()
6369
{
6470
return new ExpressionToHqlTranslationResults(Root,
65-
_itemTransformers,
66-
_listTransformers,
67-
_postExecuteTransformers,
68-
_additionalCriteria);
71+
_itemTransformers,
72+
_listTransformers,
73+
_postExecuteTransformers,
74+
_additionalCriteria,
75+
ExecuteResultTypeOverride);
6976
}
7077

7178
public void AddDistinctRootOperator()

src/NHibernate/Linq/NhLinqExpression.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ namespace NHibernate.Linq
1313
{
1414
public class NhLinqExpression : IQueryExpression
1515
{
16-
public string Key { get; private set; }
16+
public string Key { get; }
1717

1818
public System.Type Type { get; private set; }
1919

2020
public IList<NamedParameterDescriptor> ParameterDescriptors { get; private set; }
2121

22-
public NhLinqExpressionReturnType ReturnType { get; private set; }
22+
public NhLinqExpressionReturnType ReturnType { get; }
2323

24-
public IDictionary<string, Tuple<object, IType>> ParameterValuesByName { get; private set; }
24+
public IDictionary<string, Tuple<object, IType>> ParameterValuesByName { get; }
2525

2626
public ExpressionToHqlTranslationResults ExpressionToHqlTranslationResults { get; private set; }
2727

28-
internal Expression _expression;
29-
internal IDictionary<ConstantExpression, NamedParameter> _constantToParameterMap;
28+
private Expression _expression;
29+
private readonly IDictionary<ConstantExpression, NamedParameter> _constantToParameterMap;
3030

3131
public NhLinqExpression(Expression expression, ISessionFactoryImplementor sessionFactory)
3232
{
@@ -64,7 +64,10 @@ public IASTNode Translate(ISessionFactoryImplementor sessionFactory, bool filter
6464
var queryModel = NhRelinqQueryParser.Parse(_expression);
6565
var visitorParameters = new VisitorParameters(sessionFactory, _constantToParameterMap, requiredHqlParameters, querySourceNamer);
6666

67-
ExpressionToHqlTranslationResults = QueryModelVisitor.GenerateHqlQuery(queryModel, visitorParameters, true);
67+
ExpressionToHqlTranslationResults = QueryModelVisitor.GenerateHqlQuery(queryModel, visitorParameters, true, ReturnType);
68+
69+
if (ExpressionToHqlTranslationResults.ExecuteResultTypeOverride != null)
70+
Type = ExpressionToHqlTranslationResults.ExecuteResultTypeOverride;
6871

6972
ParameterDescriptors = requiredHqlParameters.AsReadOnly();
7073

@@ -75,6 +78,8 @@ internal void CopyExpressionTranslation(NhLinqExpression other)
7578
{
7679
ExpressionToHqlTranslationResults = other.ExpressionToHqlTranslationResults;
7780
ParameterDescriptors = other.ParameterDescriptors;
81+
// Type could have been overridden by translation.
82+
Type = other.Type;
7883
}
7984
}
8085
}

src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ protected HqlTreeNode VisitConditionalExpression(ConditionalExpression expressio
542542

543543
protected HqlTreeNode VisitSubQueryExpression(SubQueryExpression expression)
544544
{
545-
ExpressionToHqlTranslationResults query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameters, false);
545+
ExpressionToHqlTranslationResults query = QueryModelVisitor.GenerateHqlQuery(expression.QueryModel, _parameters, false, null);
546546
return query.Statement;
547547
}
548548

0 commit comments

Comments
 (0)