1- // Copyright (C) 2012-2021 Xtensive LLC.
1+ // Copyright (C) 2012-2022 Xtensive LLC.
22// This code is distributed under MIT license terms.
33// See the License.txt file in the project root for more information.
44// Created by: Denis Krjuchkov
77using System ;
88using System . Linq ;
99using System . Linq . Expressions ;
10+ using System . Reflection ;
1011using System . Threading ;
1112using System . Threading . Tasks ;
1213using Xtensive . Caching ;
@@ -19,6 +20,8 @@ namespace Xtensive.Orm.Internals
1920{
2021 internal class CompiledQueryRunner
2122 {
23+ private static readonly Func < FieldInfo , bool > FieldIsSimple = fieldInfo => IsSimpleType ( fieldInfo . FieldType ) ;
24+
2225 private readonly Domain domain ;
2326 private readonly Session session ;
2427 private readonly QueryEndpoint endpoint ;
@@ -108,7 +111,7 @@ private DelayedQuery<TElement> CreateDelayedSequenceQuery<TElement>(
108111 private ParameterizedQuery GetScalarQuery < TResult > (
109112 Func < QueryEndpoint , TResult > query , bool executeAsSideEffect , out TResult result )
110113 {
111- AllocateParameterAndReplacer ( ) ;
114+ var cacheable = AllocateParameterAndReplacer ( ) ;
112115
113116 var parameterContext = new ParameterContext ( outerContext ) ;
114117 parameterContext . SetValue ( queryParameter , queryTarget ) ;
@@ -123,7 +126,9 @@ private ParameterizedQuery GetScalarQuery<TResult>(
123126 throw new NotSupportedException ( Strings . ExNonLinqCallsAreNotSupportedWithinQueryExecuteDelayed ) ;
124127 }
125128
126- PutCachedQuery ( parameterizedQuery ) ;
129+ if ( cacheable ) {
130+ PutCachedQuery ( parameterizedQuery ) ;
131+ }
127132 return parameterizedQuery ;
128133 }
129134
@@ -135,24 +140,26 @@ private ParameterizedQuery GetSequenceQuery<TElement>(
135140 return parameterizedQuery ;
136141 }
137142
138- AllocateParameterAndReplacer ( ) ;
143+ var cacheable = AllocateParameterAndReplacer ( ) ;
139144 var scope = new CompiledQueryProcessingScope ( queryParameter , queryParameterReplacer ) ;
140145 using ( scope . Enter ( ) ) {
141146 var result = query . Invoke ( endpoint ) ;
142147 var translatedQuery = endpoint . Provider . Translate ( result . Expression ) ;
143148 parameterizedQuery = ( ParameterizedQuery ) translatedQuery ;
144149 }
145150
146- PutCachedQuery ( parameterizedQuery ) ;
151+ if ( cacheable ) {
152+ PutCachedQuery ( parameterizedQuery ) ;
153+ }
147154 return parameterizedQuery ;
148155 }
149156
150- private void AllocateParameterAndReplacer ( )
157+ private bool AllocateParameterAndReplacer ( )
151158 {
152159 if ( queryTarget == null ) {
153160 queryParameter = null ;
154161 queryParameterReplacer = new ExtendedExpressionReplacer ( e => e ) ;
155- return ;
162+ return true ;
156163 }
157164
158165 var closureType = queryTarget . GetType ( ) ;
@@ -192,6 +199,25 @@ private void AllocateParameterAndReplacer()
192199 }
193200 return null ;
194201 } ) ;
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+ }
195221 }
196222
197223 private ParameterizedQuery GetCachedQuery ( ) =>
0 commit comments