|
15 | 15 |
|
16 | 16 | namespace Xtensive.Orm.Internals.Prefetch |
17 | 17 | { |
18 | | - [Serializable] |
19 | | - internal sealed class EntityGroupTask : IEquatable<EntityGroupTask> |
| 18 | + internal readonly struct RecordSetCacheKey : IEquatable<RecordSetCacheKey> |
20 | 19 | { |
21 | | - #region Nested classes |
| 20 | + public readonly int[] ColumnIndexes; |
| 21 | + public readonly TypeInfo Type; |
| 22 | + private readonly int cachedHashCode; |
22 | 23 |
|
23 | | - private struct CacheKey : IEquatable<CacheKey> |
| 24 | + public bool Equals(RecordSetCacheKey other) |
24 | 25 | { |
25 | | - public readonly int[] ColumnIndexes; |
26 | | - public readonly TypeInfo Type; |
27 | | - private readonly int cachedHashCode; |
| 26 | + if (!Type.Equals(other.Type)) { |
| 27 | + return false; |
| 28 | + } |
28 | 29 |
|
29 | | - public bool Equals(CacheKey other) |
30 | | - { |
31 | | - if (!Type.Equals(other.Type)) { |
32 | | - return false; |
33 | | - } |
| 30 | + if (ColumnIndexes.Length != other.ColumnIndexes.Length) { |
| 31 | + return false; |
| 32 | + } |
34 | 33 |
|
35 | | - if (ColumnIndexes.Length != other.ColumnIndexes.Length) { |
| 34 | + for (var i = ColumnIndexes.Length - 1; i >= 0; i--) { |
| 35 | + if (ColumnIndexes[i] != other.ColumnIndexes[i]) { |
36 | 36 | return false; |
37 | 37 | } |
38 | | - |
39 | | - for (var i = ColumnIndexes.Length - 1; i >= 0; i--) { |
40 | | - if (ColumnIndexes[i] != other.ColumnIndexes[i]) { |
41 | | - return false; |
42 | | - } |
43 | | - } |
44 | | - |
45 | | - return true; |
46 | 38 | } |
47 | 39 |
|
48 | | - public override bool Equals(object obj) => |
49 | | - obj is CacheKey other && Equals(other); |
| 40 | + return true; |
| 41 | + } |
50 | 42 |
|
51 | | - public override int GetHashCode() => cachedHashCode; |
| 43 | + public override bool Equals(object obj) => |
| 44 | + obj is RecordSetCacheKey other && Equals(other); |
52 | 45 |
|
| 46 | + public override int GetHashCode() => cachedHashCode; |
53 | 47 |
|
54 | | - // Constructors |
55 | 48 |
|
56 | | - public CacheKey(int[] columnIndexes, TypeInfo type, int cachedHashCode) |
57 | | - { |
58 | | - ColumnIndexes = columnIndexes; |
59 | | - Type = type; |
60 | | - this.cachedHashCode = cachedHashCode; |
61 | | - } |
62 | | - } |
| 49 | + // Constructors |
63 | 50 |
|
64 | | - #endregion |
| 51 | + public RecordSetCacheKey(int[] columnIndexes, TypeInfo type, int cachedHashCode) |
| 52 | + { |
| 53 | + ColumnIndexes = columnIndexes; |
| 54 | + Type = type; |
| 55 | + this.cachedHashCode = cachedHashCode; |
| 56 | + } |
| 57 | + } |
65 | 58 |
|
| 59 | + [Serializable] |
| 60 | + internal sealed class EntityGroupTask : IEquatable<EntityGroupTask> |
| 61 | + { |
66 | 62 | private const int MaxKeyCountInOneStatement = 40; |
67 | | - private static readonly object recordSetCachingRegion = new object(); |
68 | 63 | private static readonly Parameter<IEnumerable<Tuple>> includeParameter = |
69 | 64 | new Parameter<IEnumerable<Tuple>>("Keys"); |
70 | 65 |
|
| 66 | + private static readonly Func<RecordSetCacheKey, CompilableProvider> CreateRecordSet = cachingKey => { |
| 67 | + var selectedColumnIndexes = cachingKey.ColumnIndexes; |
| 68 | + var keyColumnsCount = cachingKey.Type.Indexes.PrimaryIndex.KeyColumns.Count; |
| 69 | + var keyColumnIndexes = new int[keyColumnsCount]; |
| 70 | + foreach (var index in Enumerable.Range(0, keyColumnsCount)) { |
| 71 | + keyColumnIndexes[index] = index; |
| 72 | + } |
| 73 | + |
| 74 | + var columnCollectionLength = cachingKey.Type.Indexes.PrimaryIndex.Columns.Count; |
| 75 | + return cachingKey.Type.Indexes.PrimaryIndex.GetQuery().Include(IncludeAlgorithm.ComplexCondition, |
| 76 | + true, context => context.GetValue(includeParameter), $"includeColumnName-{Guid.NewGuid()}", |
| 77 | + keyColumnIndexes).Filter(t => t.GetValue<bool>(columnCollectionLength)).Select(selectedColumnIndexes); |
| 78 | + }; |
| 79 | + |
71 | 80 | private Dictionary<Key, bool> keys; |
72 | 81 | private readonly TypeInfo type; |
73 | 82 | private readonly PrefetchManager manager; |
74 | 83 | private List<QueryTask> queryTasks; |
75 | | - private readonly CacheKey cacheKey; |
| 84 | + private readonly RecordSetCacheKey cacheKey; |
76 | 85 |
|
77 | 86 | public CompilableProvider Provider { get; private set; } |
78 | 87 |
|
@@ -132,30 +141,12 @@ private QueryTask CreateQueryTask(List<Tuple> currentKeySet) |
132 | 141 | { |
133 | 142 | var parameterContext = new ParameterContext(); |
134 | 143 | parameterContext.SetValue(includeParameter, currentKeySet); |
135 | | - object key = new Pair<object, CacheKey>(recordSetCachingRegion, cacheKey); |
136 | | - Func<object, object> generator = CreateRecordSet; |
137 | 144 | var session = manager.Owner.Session; |
138 | | - Provider = (CompilableProvider) session.StorageNode.InternalQueryCache.GetOrAdd(key, generator); |
| 145 | + Provider = session.StorageNode.InternalRecordSetCache.GetOrAdd(cacheKey, CreateRecordSet); |
139 | 146 | var executableProvider = session.Compile(Provider); |
140 | 147 | return new QueryTask(executableProvider, session.GetLifetimeToken(), parameterContext); |
141 | 148 | } |
142 | 149 |
|
143 | | - private static CompilableProvider CreateRecordSet(object cachingKey) |
144 | | - { |
145 | | - var pair = (Pair<object, CacheKey>) cachingKey; |
146 | | - var selectedColumnIndexes = pair.Second.ColumnIndexes; |
147 | | - var keyColumnsCount = pair.Second.Type.Indexes.PrimaryIndex.KeyColumns.Count; |
148 | | - var keyColumnIndexes = new int[keyColumnsCount]; |
149 | | - foreach (var index in Enumerable.Range(0, keyColumnsCount)) { |
150 | | - keyColumnIndexes[index] = index; |
151 | | - } |
152 | | - |
153 | | - var columnCollectionLength = pair.Second.Type.Indexes.PrimaryIndex.Columns.Count; |
154 | | - return pair.Second.Type.Indexes.PrimaryIndex.GetQuery().Include(IncludeAlgorithm.ComplexCondition, |
155 | | - true, context => context.GetValue(includeParameter), $"includeColumnName-{Guid.NewGuid()}", |
156 | | - keyColumnIndexes).Filter(t => t.GetValue<bool>(columnCollectionLength)).Select(selectedColumnIndexes); |
157 | | - } |
158 | | - |
159 | 150 | private void PutLoadedStatesInCache(IEnumerable<Tuple> queryResult, EntityDataReader reader, |
160 | 151 | HashSet<Key> foundedKeys) |
161 | 152 | { |
@@ -221,7 +212,7 @@ public EntityGroupTask(TypeInfo type, int[] columnIndexes, PrefetchManager manag |
221 | 212 | } |
222 | 213 |
|
223 | 214 | cachedHashCode ^= type.GetHashCode(); |
224 | | - cacheKey = new CacheKey(columnIndexes, type, cachedHashCode); |
| 215 | + cacheKey = new RecordSetCacheKey(columnIndexes, type, cachedHashCode); |
225 | 216 | } |
226 | 217 | } |
227 | 218 | } |
0 commit comments