diff --git a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryProcessingScope.cs b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryProcessingScope.cs
index fa0dde9aeb..e06bd664a8 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryProcessingScope.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryProcessingScope.cs
@@ -13,7 +13,7 @@ namespace Xtensive.Orm.Internals
{
internal sealed class CompiledQueryProcessingScope
{
- private TranslatedQuery parameterizedQuery;
+ private ParameterizedQuery parameterizedQuery;
public Parameter QueryParameter { get; }
public ExtendedExpressionReplacer QueryParameterReplacer { get; }
@@ -43,7 +43,7 @@ public ThreadBindingToken(CompiledQueryProcessingScope scope)
public ThreadBindingToken Enter() => new ThreadBindingToken(this);
/// Second attempt to set this property.
- public TranslatedQuery ParameterizedQuery {
+ public ParameterizedQuery ParameterizedQuery {
get => parameterizedQuery;
set {
if (parameterizedQuery != null) {
diff --git a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs
index 585449d9e6..1eed8ec37d 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2021 Xtensive LLC.
+// Copyright (C) 2012-2022 Xtensive LLC.
// This code is distributed under MIT license terms.
// See the License.txt file in the project root for more information.
// Created by: Denis Krjuchkov
@@ -7,6 +7,7 @@
using System;
using System.Linq;
using System.Linq.Expressions;
+using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Xtensive.Caching;
@@ -19,6 +20,8 @@ namespace Xtensive.Orm.Internals
{
internal class CompiledQueryRunner
{
+ private static readonly Func FieldIsSimple = fieldInfo => TypeIsSimple(fieldInfo.FieldType);
+
private readonly Domain domain;
private readonly Session session;
private readonly QueryEndpoint endpoint;
@@ -44,7 +47,7 @@ public QueryResult ExecuteCompiled(Func(Func query)
{
var parameterizedQuery = GetCachedQuery();
- if (parameterizedQuery!=null) {
+ if (parameterizedQuery != null) {
return parameterizedQuery.ExecuteScalar(session, CreateParameterContext(parameterizedQuery));
}
@@ -65,12 +68,12 @@ public Task> ExecuteCompiledAsync(
public Task> ExecuteCompiledAsync(
Func> query, CancellationToken token) =>
- ExecuteCompiledAsync((Func>)query, token);
+ ExecuteCompiledAsync((Func>) query, token);
public Task ExecuteCompiledAsync(Func query, CancellationToken token)
{
var parameterizedQuery = GetCachedQuery();
- if (parameterizedQuery!=null) {
+ if (parameterizedQuery != null) {
token.ThrowIfCancellationRequested();
return parameterizedQuery.ExecuteScalarAsync(session, CreateParameterContext(parameterizedQuery), token);
}
@@ -108,7 +111,7 @@ private DelayedQuery CreateDelayedSequenceQuery(
private ParameterizedQuery GetScalarQuery(
Func query, bool executeAsSideEffect, out TResult result)
{
- AllocateParameterAndReplacer();
+ var cacheable = AllocateParameterAndReplacer();
var parameterContext = new ParameterContext(outerContext);
parameterContext.SetValue(queryParameter, queryTarget);
@@ -118,12 +121,14 @@ private ParameterizedQuery GetScalarQuery(
result = query.Invoke(endpoint);
}
- var parameterizedQuery = (ParameterizedQuery) scope.ParameterizedQuery;
- if (parameterizedQuery==null && queryTarget!=null) {
+ var parameterizedQuery = scope.ParameterizedQuery;
+ if (parameterizedQuery == null && queryTarget != null) {
throw new NotSupportedException(Strings.ExNonLinqCallsAreNotSupportedWithinQueryExecuteDelayed);
}
- PutCachedQuery(parameterizedQuery);
+ if (cacheable) {
+ PutCachedQuery(parameterizedQuery);
+ }
return parameterizedQuery;
}
@@ -131,11 +136,11 @@ private ParameterizedQuery GetSequenceQuery(
Func> query)
{
var parameterizedQuery = GetCachedQuery();
- if (parameterizedQuery!=null) {
+ if (parameterizedQuery != null) {
return parameterizedQuery;
}
- AllocateParameterAndReplacer();
+ var cacheable = AllocateParameterAndReplacer();
var scope = new CompiledQueryProcessingScope(queryParameter, queryParameterReplacer);
using (scope.Enter()) {
var result = query.Invoke(endpoint);
@@ -143,16 +148,19 @@ private ParameterizedQuery GetSequenceQuery(
parameterizedQuery = (ParameterizedQuery) translatedQuery;
}
- PutCachedQuery(parameterizedQuery);
+ if (cacheable) {
+ PutCachedQuery(parameterizedQuery);
+ }
return parameterizedQuery;
}
- private void AllocateParameterAndReplacer()
+ // Returns true is query is cacheable (target contains only simple-type captured vars).
+ private bool AllocateParameterAndReplacer()
{
if (queryTarget == null) {
queryParameter = null;
queryParameterReplacer = new ExtendedExpressionReplacer(e => e);
- return;
+ return true;
}
var closureType = queryTarget.GetType();
@@ -160,38 +168,43 @@ private void AllocateParameterAndReplacer()
var valueMemberInfo = parameterType.GetProperty(nameof(Parameter