Skip to content

Replace object queryKey by value-type QueryKey #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions Orm/Xtensive.Orm/Orm/Domain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,9 @@ public static Domain Demand()

internal KeyGeneratorRegistry KeyGenerators { get; private set; }

internal ConcurrentDictionary<TypeInfo, IReadOnlyList<PrefetchFieldDescriptor>> PrefetchFieldDescriptorCache { get; } =
new ConcurrentDictionary<TypeInfo, IReadOnlyList<PrefetchFieldDescriptor>>();
internal ConcurrentDictionary<TypeInfo, IReadOnlyList<PrefetchFieldDescriptor>> PrefetchFieldDescriptorCache { get; } = new();

internal FastConcurrentLruCache<object, (object, ParameterizedQuery)> QueryCache { get; }
internal FastConcurrentLruCache<QueryKey, (QueryKey Key, ParameterizedQuery Query)> QueryCache { get; }

internal ConcurrentDictionary<Type, System.Linq.Expressions.MethodCallExpression> RootCallExpressionsCache { get; } = new();

Expand Down Expand Up @@ -430,7 +429,7 @@ internal Domain(DomainConfiguration configuration, object upgradeContextCookie,
GenericKeyFactories = new ConcurrentDictionary<TypeInfo, GenericKeyFactory>();
EntityDataReader = new EntityDataReader(this);
KeyGenerators = new KeyGeneratorRegistry();
QueryCache = new FastConcurrentLruCache<object, (object, ParameterizedQuery)>(Configuration.QueryCacheSize, k => k.Item1);
QueryCache = new(Configuration.QueryCacheSize, k => k.Key);
Extensions = new ExtensionCollection();
UpgradeContextCookie = upgradeContextCookie;
SingleConnection = singleConnection;
Expand Down
32 changes: 19 additions & 13 deletions Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
{
session = endpoint.Provider.Session;
domain = session.Domain;
Expand All @@ -227,9 +221,21 @@ 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 is MethodInfo methodInfo ? (methodInfo, methodInfo.MetadataToken, methodInfo.Module.ModuleHandle) : (key, 0, default),
queryTarget, outerContext)
{
}
}
}
3 changes: 3 additions & 0 deletions Orm/Xtensive.Orm/Orm/QueryEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,9 @@ public DelayedScalarQuery<TResult> CreateDelayedQuery<TResult>(Func<QueryEndpoin
public DelayedQuery<TElement> CreateDelayedQuery<TElement>(object key, Func<QueryEndpoint, IQueryable<TElement>> query) =>
new CompiledQueryRunner(this, key, query.Target).CreateDelayedQuery(query);

public DelayedQuery<TElement> CreateDelayedQuery<TElement>(MethodInfo key, Func<QueryEndpoint, IQueryable<TElement>> query) =>
new CompiledQueryRunner(this, key, query.Target).CreateDelayedQuery(query);

/// <summary>
/// Creates future query and registers it for the later execution.
/// The associated query will be cached.
Expand Down
12 changes: 5 additions & 7 deletions Orm/Xtensive.Orm/Orm/StorageNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<object, (object, Linq.ParameterizedQuery)>) handlers.Domain.QueryCache;
foreach (var key in queryCache.Keys.Where(k => k is ValueTuple<object, string> 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;
Expand Down