From 189a689600dba97c178c38592d01427d0339d089 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Thu, 17 Apr 2025 11:42:07 -0700 Subject: [PATCH 1/3] Replace `object` queryKey by value-type `QueryKey` --- Orm/Xtensive.Orm/Orm/Domain.cs | 7 ++--- .../Orm/Internals/CompiledQueryRunner.cs | 30 +++++++++++-------- Orm/Xtensive.Orm/Orm/StorageNodeManager.cs | 12 ++++---- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Domain.cs b/Orm/Xtensive.Orm/Orm/Domain.cs index fda240a5f..93d1845ee 100644 --- a/Orm/Xtensive.Orm/Orm/Domain.cs +++ b/Orm/Xtensive.Orm/Orm/Domain.cs @@ -128,10 +128,9 @@ public static Domain Demand() internal KeyGeneratorRegistry KeyGenerators { get; private set; } - internal ConcurrentDictionary> PrefetchFieldDescriptorCache { get; } = - new ConcurrentDictionary>(); + internal ConcurrentDictionary> PrefetchFieldDescriptorCache { get; } = new(); - internal FastConcurrentLruCache QueryCache { get; } + internal FastConcurrentLruCache QueryCache { get; } internal ConcurrentDictionary RootCallExpressionsCache { get; } = new(); @@ -430,7 +429,7 @@ internal Domain(DomainConfiguration configuration, object upgradeContextCookie, GenericKeyFactories = new ConcurrentDictionary(); EntityDataReader = new EntityDataReader(this); KeyGenerators = new KeyGeneratorRegistry(); - QueryCache = new FastConcurrentLruCache(Configuration.QueryCacheSize, k => k.Item1); + QueryCache = new(Configuration.QueryCacheSize, k => k.Key); Extensions = new ExtensionCollection(); UpgradeContextCookie = upgradeContextCookie; SingleConnection = singleConnection; diff --git a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs index 8b5445650..4d07fcffd 100644 --- a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs +++ b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs @@ -4,29 +4,23 @@ // Created by: Denis Krjuchkov // Created: 2012.01.27 -using System; -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Xtensive.Caching; using Xtensive.Core; using Xtensive.Orm.Linq; using Xtensive.Orm.Linq.Expressions.Visitors; -using Xtensive.Orm.Providers; -using Xtensive.Orm.Rse.Providers; using Xtensive.Reflection; namespace Xtensive.Orm.Internals { + internal record struct QueryKey(object Key, int MetadataToken, ModuleHandle ModuleHandle, string StorageNodeId); + internal class CompiledQueryRunner { private readonly Domain domain; private readonly Session session; private readonly QueryEndpoint endpoint; - private readonly object queryKey; + private readonly QueryKey queryKey; private readonly object queryTarget; private readonly ParameterContext outerContext; @@ -217,7 +211,7 @@ private ParameterContext CreateParameterContext(ParameterizedQuery query) return parameterContext; } - public CompiledQueryRunner(QueryEndpoint endpoint, object queryKey, object queryTarget, ParameterContext outerContext = null) + private CompiledQueryRunner(QueryEndpoint endpoint, (object Key, int MetadataToken, ModuleHandle ModuleHandle) keyParts, object queryTarget, ParameterContext outerContext = null) { session = endpoint.Provider.Session; domain = session.Domain; @@ -227,9 +221,19 @@ public CompiledQueryRunner(QueryEndpoint endpoint, object queryKey, object query this.outerContext = outerContext; var domainConfig = domain.Configuration; - this.queryKey = domainConfig.ShareStorageSchemaOverNodes && domainConfig.PreferTypeIdsAsQueryParameters - ? queryKey - : (queryKey, session.StorageNodeId); + queryKey = new(keyParts.Key, keyParts.MetadataToken, keyParts.ModuleHandle, + domainConfig.ShareStorageSchemaOverNodes && domainConfig.PreferTypeIdsAsQueryParameters ? null : session.StorageNodeId + ); + } + + public CompiledQueryRunner(QueryEndpoint endpoint, MethodInfo methodInfo, object queryTarget, ParameterContext outerContext = null) + : this(endpoint, (methodInfo, methodInfo.MetadataToken, methodInfo.Module.ModuleHandle), queryTarget, outerContext) + { + } + + public CompiledQueryRunner(QueryEndpoint endpoint, object key, object queryTarget, ParameterContext outerContext = null) + : this(endpoint, (key, 0, default), queryTarget, outerContext) + { } } } diff --git a/Orm/Xtensive.Orm/Orm/StorageNodeManager.cs b/Orm/Xtensive.Orm/Orm/StorageNodeManager.cs index f2451ee8c..b3be3e300 100644 --- a/Orm/Xtensive.Orm/Orm/StorageNodeManager.cs +++ b/Orm/Xtensive.Orm/Orm/StorageNodeManager.cs @@ -64,13 +64,11 @@ public bool RemoveNode([NotNull] string nodeId, bool clearQueryCache = false) if (removeResult && clearQueryCache) { var domainConfig = handlers.Domain.Configuration; - if (domainConfig.ShareStorageSchemaOverNodes && domainConfig.PreferTypeIdsAsQueryParameters) { - return removeResult; - } - - var queryCache = (Caching.FastConcurrentLruCache) handlers.Domain.QueryCache; - foreach (var key in queryCache.Keys.Where(k => k is ValueTuple pair && pair.Item2 == nodeId).ToList()) { - queryCache.RemoveKey(key); + if (!(domainConfig.ShareStorageSchemaOverNodes && domainConfig.PreferTypeIdsAsQueryParameters)) { + var queryCache = handlers.Domain.QueryCache; + foreach (var key in queryCache.Keys.Where(k => k.StorageNodeId == nodeId).ToList()) { + queryCache.RemoveKey(key); + } } } return removeResult; From 96e5fb42567123af2adf17f070a3f05e4b065e75 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Thu, 17 Apr 2025 12:10:33 -0700 Subject: [PATCH 2/3] remove default arg --- Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs index 4d07fcffd..8f2c49459 100644 --- a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs +++ b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs @@ -211,7 +211,7 @@ private ParameterContext CreateParameterContext(ParameterizedQuery query) return parameterContext; } - private CompiledQueryRunner(QueryEndpoint endpoint, (object Key, int MetadataToken, ModuleHandle ModuleHandle) keyParts, object queryTarget, ParameterContext outerContext = null) + private CompiledQueryRunner(QueryEndpoint endpoint, (object Key, int MetadataToken, ModuleHandle ModuleHandle) keyParts, object queryTarget, ParameterContext outerContext) { session = endpoint.Provider.Session; domain = session.Domain; From 4247df6a3ad7b0bd862c555db75c3a37ceff9665 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Thu, 17 Apr 2025 13:19:32 -0700 Subject: [PATCH 3/3] Fix CachingFutureSequenceTest --- Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs | 4 +++- Orm/Xtensive.Orm/Orm/QueryEndpoint.cs | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs index 8f2c49459..7fa41dd1a 100644 --- a/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs +++ b/Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs @@ -232,7 +232,9 @@ public CompiledQueryRunner(QueryEndpoint endpoint, MethodInfo methodInfo, object } public CompiledQueryRunner(QueryEndpoint endpoint, object key, object queryTarget, ParameterContext outerContext = null) - : this(endpoint, (key, 0, default), queryTarget, outerContext) + : this(endpoint, + key is MethodInfo methodInfo ? (methodInfo, methodInfo.MetadataToken, methodInfo.Module.ModuleHandle) : (key, 0, default), + queryTarget, outerContext) { } } diff --git a/Orm/Xtensive.Orm/Orm/QueryEndpoint.cs b/Orm/Xtensive.Orm/Orm/QueryEndpoint.cs index 241a0bb5f..ae75a5d49 100644 --- a/Orm/Xtensive.Orm/Orm/QueryEndpoint.cs +++ b/Orm/Xtensive.Orm/Orm/QueryEndpoint.cs @@ -880,6 +880,9 @@ public DelayedScalarQuery CreateDelayedQuery(Func CreateDelayedQuery(object key, Func> query) => new CompiledQueryRunner(this, key, query.Target).CreateDelayedQuery(query); + public DelayedQuery CreateDelayedQuery(MethodInfo key, Func> query) => + new CompiledQueryRunner(this, key, query.Target).CreateDelayedQuery(query); + /// /// Creates future query and registers it for the later execution. /// The associated query will be cached.