Skip to content

Commit 09d0352

Browse files
committed
Fix Issue 224
1 parent 49f59b0 commit 09d0352

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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
@@ -7,6 +7,7 @@
77
using System;
88
using System.Linq;
99
using System.Linq.Expressions;
10+
using System.Reflection;
1011
using System.Threading;
1112
using System.Threading.Tasks;
1213
using 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 => TypeIsSimple(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 !closureType.Name.Contains("<>c__DisplayClass") // 'DisplayClass' is generated class for captured objects
204+
|| closureType.GetFields().All(FieldIsSimple);
205+
}
206+
207+
private static bool TypeIsSimple(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.IReadOnlyList))
213+
&& TypeIsSimple(typeInfo.GetGenericArguments()[0]);
214+
}
215+
else if (typeInfo.IsArray) {
216+
return TypeIsSimple(typeInfo.GetElementType());
217+
}
218+
else {
219+
return typeInfo.IsPrimitive || typeInfo.IsEnum || type == WellKnownTypes.String || type == WellKnownTypes.Decimal;
220+
}
195221
}
196222

197223
private ParameterizedQuery GetCachedQuery() =>

Orm/Xtensive.Orm/Reflection/WellKnownTypes.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// Copyright (C) 2020 Xtensive LLC.
1+
// Copyright (C) 2020-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

55
using System;
6+
using System.Collections.Generic;
67
using System.Linq;
78
using System.Linq.Expressions;
89
using System.Reflection;
@@ -73,6 +74,7 @@ internal static class WellKnownTypes
7374

7475
public static readonly Type ByteArray = typeof(byte[]);
7576
public static readonly Type ObjectArray = typeof(object[]);
77+
public static readonly Type IReadOnlyList = typeof(IReadOnlyList<>);
7678

7779
public static readonly Type DefaultMemberAttribute = typeof(DefaultMemberAttribute);
7880
}

0 commit comments

Comments
 (0)