1
- // Copyright (C) 2012-2021 Xtensive LLC.
1
+ // Copyright (C) 2012-2022 Xtensive LLC.
2
2
// This code is distributed under MIT license terms.
3
3
// See the License.txt file in the project root for more information.
4
4
// Created by: Denis Krjuchkov
7
7
using System ;
8
8
using System . Linq ;
9
9
using System . Linq . Expressions ;
10
+ using System . Reflection ;
10
11
using System . Threading ;
11
12
using System . Threading . Tasks ;
12
13
using Xtensive . Caching ;
@@ -19,6 +20,8 @@ namespace Xtensive.Orm.Internals
19
20
{
20
21
internal class CompiledQueryRunner
21
22
{
23
+ private static readonly Func < FieldInfo , bool > FieldIsSimple = fieldInfo => IsSimpleType ( fieldInfo . FieldType ) ;
24
+
22
25
private readonly Domain domain ;
23
26
private readonly Session session ;
24
27
private readonly QueryEndpoint endpoint ;
@@ -108,7 +111,7 @@ private DelayedQuery<TElement> CreateDelayedSequenceQuery<TElement>(
108
111
private ParameterizedQuery GetScalarQuery < TResult > (
109
112
Func < QueryEndpoint , TResult > query , bool executeAsSideEffect , out TResult result )
110
113
{
111
- AllocateParameterAndReplacer ( ) ;
114
+ var cacheable = AllocateParameterAndReplacer ( ) ;
112
115
113
116
var parameterContext = new ParameterContext ( outerContext ) ;
114
117
parameterContext . SetValue ( queryParameter , queryTarget ) ;
@@ -123,7 +126,9 @@ private ParameterizedQuery GetScalarQuery<TResult>(
123
126
throw new NotSupportedException ( Strings . ExNonLinqCallsAreNotSupportedWithinQueryExecuteDelayed ) ;
124
127
}
125
128
126
- PutCachedQuery ( parameterizedQuery ) ;
129
+ if ( cacheable ) {
130
+ PutCachedQuery ( parameterizedQuery ) ;
131
+ }
127
132
return parameterizedQuery ;
128
133
}
129
134
@@ -135,24 +140,26 @@ private ParameterizedQuery GetSequenceQuery<TElement>(
135
140
return parameterizedQuery ;
136
141
}
137
142
138
- AllocateParameterAndReplacer ( ) ;
143
+ var cacheable = AllocateParameterAndReplacer ( ) ;
139
144
var scope = new CompiledQueryProcessingScope ( queryParameter , queryParameterReplacer ) ;
140
145
using ( scope . Enter ( ) ) {
141
146
var result = query . Invoke ( endpoint ) ;
142
147
var translatedQuery = endpoint . Provider . Translate ( result . Expression ) ;
143
148
parameterizedQuery = ( ParameterizedQuery ) translatedQuery ;
144
149
}
145
150
146
- PutCachedQuery ( parameterizedQuery ) ;
151
+ if ( cacheable ) {
152
+ PutCachedQuery ( parameterizedQuery ) ;
153
+ }
147
154
return parameterizedQuery ;
148
155
}
149
156
150
- private void AllocateParameterAndReplacer ( )
157
+ private bool AllocateParameterAndReplacer ( )
151
158
{
152
159
if ( queryTarget == null ) {
153
160
queryParameter = null ;
154
161
queryParameterReplacer = new ExtendedExpressionReplacer ( e => e ) ;
155
- return ;
162
+ return true ;
156
163
}
157
164
158
165
var closureType = queryTarget . GetType ( ) ;
@@ -192,6 +199,25 @@ private void AllocateParameterAndReplacer()
192
199
}
193
200
return null ;
194
201
} ) ;
202
+
203
+ return ! TypeHelper . IsClosure ( closureType )
204
+ || closureType . GetFields ( ) . All ( FieldIsSimple ) ;
205
+ }
206
+
207
+ private static bool IsSimpleType ( Type type )
208
+ {
209
+ var typeInfo = type . GetTypeInfo ( ) ;
210
+ if ( typeInfo . IsGenericType ) {
211
+ var genericDef = typeInfo . GetGenericTypeDefinition ( ) ;
212
+ return ( genericDef == WellKnownTypes . NullableOfT || genericDef . IsAssignableTo ( WellKnownTypes . IReadOnlyListOfT ) )
213
+ && IsSimpleType ( typeInfo . GetGenericArguments ( ) [ 0 ] ) ;
214
+ }
215
+ else if ( typeInfo . IsArray ) {
216
+ return IsSimpleType ( typeInfo . GetElementType ( ) ) ;
217
+ }
218
+ else {
219
+ return typeInfo . IsPrimitive || typeInfo . IsEnum || type == WellKnownTypes . String || type == WellKnownTypes . Decimal ;
220
+ }
195
221
}
196
222
197
223
private ParameterizedQuery GetCachedQuery ( ) =>
0 commit comments