@@ -112,60 +112,81 @@ internal static void SetParameterTypes(
112
112
continue ;
113
113
}
114
114
115
- var parameterRelatedExpressions = new List < Expression > ( ) ;
116
- foreach ( var expression in constantExpressions )
115
+ namedParameter . Type = GetParameterType ( sessionFactory , constantExpressions , visitor , namedParameter ) ;
116
+ }
117
+ }
118
+
119
+ private static HashSet < IType > GetCandidateTypes (
120
+ ISessionFactoryImplementor sessionFactory ,
121
+ IEnumerable < ConstantExpression > constantExpressions ,
122
+ ConstantTypeLocatorVisitor visitor )
123
+ {
124
+ var parameterRelatedExpressions = new List < Expression > ( ) ;
125
+ foreach ( var expression in constantExpressions )
126
+ {
127
+ if ( visitor . RelatedExpressions . TryGetValue ( expression , out var relatedExpressions ) )
117
128
{
118
- if ( visitor . RelatedExpressions . TryGetValue ( expression , out var relatedExpressions ) )
119
- {
120
- parameterRelatedExpressions . AddRange ( relatedExpressions ) ;
121
- }
129
+ parameterRelatedExpressions . AddRange ( relatedExpressions ) ;
122
130
}
131
+ }
123
132
124
- var candidateTypes = new HashSet < IType > ( ) ;
125
- // In order to get the actual type we have to check first the related member expressions, as
126
- // an enum is translated in a numeric type when used in a BinaryExpression and also it can be mapped as string.
127
- // By getting the type from a related member expression we also get the correct length in case of StringType
128
- // or precision when having a DecimalType.
129
- foreach ( var relatedExpression in parameterRelatedExpressions )
133
+ var candidateTypes = new HashSet < IType > ( ) ;
134
+ // In order to get the actual type we have to check first the related member expressions, as
135
+ // an enum is translated in a numeric type when used in a BinaryExpression and also it can be mapped as string.
136
+ // By getting the type from a related member expression we also get the correct length in case of StringType
137
+ // or precision when having a DecimalType.
138
+ foreach ( var relatedExpression in parameterRelatedExpressions )
139
+ {
140
+ if ( TryGetMappedType ( sessionFactory , relatedExpression , out var candidateType , out _ , out _ , out _ ) )
130
141
{
131
- if ( TryGetMappedType ( sessionFactory , relatedExpression , out var candidateType , out _ , out _ , out _ ) )
142
+ if ( candidateType . IsAssociationType && visitor . SequenceSelectorExpressions . Contains ( relatedExpression ) )
132
143
{
133
- if ( candidateType . IsAssociationType && visitor . SequenceSelectorExpressions . Contains ( relatedExpression ) )
134
- {
135
- var collection = ( IQueryableCollection ) ( ( IAssociationType ) candidateType ) . GetAssociatedJoinable ( sessionFactory ) ;
136
- candidateType = collection . ElementType ;
137
- }
138
-
139
- candidateTypes . Add ( candidateType ) ;
144
+ var collection =
145
+ ( IQueryableCollection ) ( ( IAssociationType ) candidateType ) . GetAssociatedJoinable ( sessionFactory ) ;
146
+ candidateType = collection . ElementType ;
140
147
}
141
- }
142
148
143
- // All constant expressions have the same type/value
144
- var constantExpression = constantExpressions . First ( ) ;
145
- var constantType = constantExpression . Type . UnwrapIfNullable ( ) ;
146
- IType type = null ;
147
- if (
148
- candidateTypes . Count == 1 &&
149
- // When comparing an integral column with a floating-point parameter, the parameter type must remain floating-point type
150
- // and the column needs to be casted in order to prevent invalid results (e.g. Where(o => o.Integer >= 2.2d)).
151
- ! ( candidateTypes . Any ( t => IntegralNumericTypes . Contains ( t . ReturnedClass ) ) && FloatingPointNumericTypes . Contains ( constantType ) )
152
- )
153
- {
154
- type = candidateTypes . FirstOrDefault ( ) ;
149
+ candidateTypes . Add ( candidateType ) ;
155
150
}
151
+ }
156
152
157
- // No related MemberExpressions was found, guess the type by value or its type when null.
158
- // When a numeric parameter is compared to different columns with different types (e.g. Where(o => o.Single >= singleParam || o.Double <= singleParam))
159
- // do not change the parameter type, but instead cast the parameter when comparing with different column types.
160
- if ( type == null )
161
- {
162
- type = constantExpression . Value != null
163
- ? ParameterHelper . TryGuessType ( constantExpression . Value , sessionFactory , namedParameter . IsCollection )
164
- : ParameterHelper . TryGuessType ( constantType , sessionFactory , namedParameter . IsCollection ) ;
165
- }
153
+ return candidateTypes ;
154
+ }
166
155
167
- namedParameter . Type = type ;
156
+ private static IType GetParameterType (
157
+ ISessionFactoryImplementor sessionFactory ,
158
+ HashSet < ConstantExpression > constantExpressions ,
159
+ ConstantTypeLocatorVisitor visitor ,
160
+ NamedParameter namedParameter )
161
+ {
162
+ var candidateTypes = GetCandidateTypes ( sessionFactory , constantExpressions , visitor ) ;
163
+
164
+ // All constant expressions have the same type/value
165
+ var constantExpression = constantExpressions . First ( ) ;
166
+ var constantType = constantExpression . Type . UnwrapIfNullable ( ) ;
167
+ IType type = null ;
168
+ if (
169
+ candidateTypes . Count == 1 &&
170
+ // When comparing an integral column with a floating-point parameter, the parameter type must remain floating-point type
171
+ // and the column needs to be casted in order to prevent invalid results (e.g. Where(o => o.Integer >= 2.2d)).
172
+ ! ( candidateTypes . Any ( t => IntegralNumericTypes . Contains ( t . ReturnedClass ) ) &&
173
+ FloatingPointNumericTypes . Contains ( constantType ) )
174
+ )
175
+ {
176
+ type = candidateTypes . FirstOrDefault ( ) ;
177
+ }
178
+
179
+ // No related MemberExpressions was found, guess the type by value or its type when null.
180
+ // When a numeric parameter is compared to different columns with different types (e.g. Where(o => o.Single >= singleParam || o.Double <= singleParam))
181
+ // do not change the parameter type, but instead cast the parameter when comparing with different column types.
182
+ if ( type == null )
183
+ {
184
+ type = constantExpression . Value != null
185
+ ? ParameterHelper . TryGuessType ( constantExpression . Value , sessionFactory , namedParameter . IsCollection )
186
+ : ParameterHelper . TryGuessType ( constantType , sessionFactory , namedParameter . IsCollection ) ;
168
187
}
188
+
189
+ return type ;
169
190
}
170
191
171
192
private class ConstantTypeLocatorVisitor : RelinqExpressionVisitor
0 commit comments