1- // Copyright (C) 2003-2010 Xtensive LLC.
2- // All rights reserved .
3- // For conditions of distribution and use, see license .
1+ // Copyright (C) 2009-2020 Xtensive LLC.
2+ // This code is distributed under MIT license terms .
3+ // See the License.txt file in the project root for more information .
44// Created by: Alexander Nikolaev
55// Created: 2009.09.09
66
@@ -28,35 +28,33 @@ private struct CacheKey : IEquatable<CacheKey>
2828 {
2929 public readonly FieldInfo ReferencingField ;
3030 public readonly int ? ItemCountLimit ;
31- private int cachedHashCode ;
31+ private readonly int cachedHashCode ;
3232
3333 public bool Equals ( CacheKey other )
3434 {
35- return ( ItemCountLimit == null ) == ( other . ItemCountLimit == null )
35+ return ( ItemCountLimit == null ) == ( other . ItemCountLimit == null )
3636 && Equals ( other . ReferencingField , ReferencingField ) ;
3737 }
3838
3939 public override bool Equals ( object obj )
4040 {
41- if ( ReferenceEquals ( null , obj ) )
41+ if ( ReferenceEquals ( null , obj ) ) {
4242 return false ;
43- if ( obj . GetType ( ) != typeof ( CacheKey ) )
43+ }
44+ if ( obj . GetType ( ) != typeof ( CacheKey ) ) {
4445 return false ;
46+ }
4547 return Equals ( ( CacheKey ) obj ) ;
4648 }
4749
48- public override int GetHashCode ( )
49- {
50- return cachedHashCode ;
51- }
52-
50+ public override int GetHashCode ( ) => cachedHashCode ;
5351
5452 // Constructors
5553
5654 public CacheKey ( FieldInfo referencingField , int ? itemCountLimit )
5755 {
58- this . ReferencingField = referencingField ;
59- this . ItemCountLimit = itemCountLimit ;
56+ ReferencingField = referencingField ;
57+ ItemCountLimit = itemCountLimit ;
6058 unchecked {
6159 cachedHashCode = ( ReferencingField . GetHashCode ( ) * 397 )
6260 ^ ( ItemCountLimit . HasValue ? 1 : 0 ) ;
@@ -69,16 +67,15 @@ public CacheKey(FieldInfo referencingField, int? itemCountLimit)
6967 private static readonly object itemsQueryCachingRegion = new object ( ) ;
7068 private static readonly Parameter < Tuple > ownerParameter = new Parameter < Tuple > ( WellKnown . KeyFieldName ) ;
7169 private static readonly Parameter < int > itemCountLimitParameter = new Parameter < int > ( "ItemCountLimit" ) ;
72- private static readonly MethodInfo getValueMethodDefinition = typeof ( Tuple )
73- . GetMethods ( BindingFlags . Public | BindingFlags . Instance )
74- . Where ( method => method . Name == "GetValue" && method . GetParameters ( ) . Length == 1
75- && method . IsGenericMethodDefinition ) . Single ( ) ;
70+ // private static readonly MethodInfo getValueMethodDefinition = typeof (Tuple)
71+ // .GetMethods(BindingFlags.Public | BindingFlags.Instance)
72+ // .Where(method => method.Name=="GetValue" && method.GetParameters().Length == 1
73+ // && method.IsGenericMethodDefinition).Single();
7674
7775 private readonly Key ownerKey ;
7876 private readonly bool isOwnerCached ;
7977 private readonly PrefetchManager manager ;
8078 private QueryTask itemsQueryTask ;
81- private int ? cachedHashCode ;
8279 private readonly PrefetchFieldDescriptor referencingFieldDescriptor ;
8380 private readonly CacheKey cacheKey ;
8481
@@ -90,80 +87,96 @@ public CacheKey(FieldInfo referencingField, int? itemCountLimit)
9087
9188 public void RegisterQueryTask ( )
9289 {
93- EntitySetState state ;
94- if ( isOwnerCached && manager . Owner . LookupState ( ownerKey , ReferencingField , out state ) )
95- if ( state == null || state . IsFullyLoaded )
90+ if ( isOwnerCached && manager . Owner . LookupState ( ownerKey , ReferencingField , out var state ) ) {
91+ if ( state == null || ( state . IsFullyLoaded && ! state . ShouldUseForcePrefetch ( referencingFieldDescriptor . PrefetchOperationId ) ) ) {
9692 return ;
93+ }
94+ }
95+
9796 itemsQueryTask = CreateQueryTask ( ) ;
9897 manager . Owner . Session . RegisterInternalDelayedQuery ( itemsQueryTask ) ;
9998 }
10099
101100 public void UpdateCache ( )
102101 {
103- if ( itemsQueryTask == null )
102+ if ( itemsQueryTask == null ) {
104103 return ;
104+ }
105+
105106 var areToNotifyAboutKeys = ! manager . Owner . Session . Domain . Model
106107 . Types [ referencingFieldDescriptor . Field . ItemType ] . IsLeaf ;
107108 var reader = manager . Owner . Session . Domain . RecordSetReader ;
108109 var records = reader . Read ( itemsQueryTask . Result , QueryProvider . Header , manager . Owner . Session ) ;
109110 var entityKeys = new List < Key > ( itemsQueryTask . Result . Count ) ;
110- List < Pair < Key , Tuple > > auxEntities = null ;
111111 var association = ReferencingField . Associations . Last ( ) ;
112- if ( association . AuxiliaryType != null )
113- auxEntities = new List < Pair < Key , Tuple > > ( itemsQueryTask . Result . Count ) ;
112+ var auxEntities = ( association . AuxiliaryType != null )
113+ ? new List < Pair < Key , Tuple > > ( itemsQueryTask . Result . Count )
114+ : null ;
115+
114116 foreach ( var record in records ) {
115- for ( int i = 0 ; i < record . Count ; i ++ ) {
117+ for ( var i = 0 ; i < record . Count ; i ++ ) {
116118 var key = record . GetKey ( i ) ;
117- if ( key == null )
119+ if ( key == null ) {
118120 continue ;
121+ }
119122 var tuple = record . GetTuple ( i ) ;
120- if ( tuple == null )
123+ if ( tuple == null ) {
121124 continue ;
122- if ( association . AuxiliaryType != null )
123- if ( i == 0 )
125+ }
126+ if ( association . AuxiliaryType != null ) {
127+ if ( i == 0 ) {
124128 auxEntities . Add ( new Pair < Key , Tuple > ( key , tuple ) ) ;
129+ }
125130 else {
126131 manager . SaveStrongReference ( manager . Owner . UpdateState ( key , tuple ) ) ;
127132 entityKeys . Add ( key ) ;
128- if ( areToNotifyAboutKeys )
133+ if ( areToNotifyAboutKeys ) {
129134 referencingFieldDescriptor . NotifySubscriber ( ownerKey , key ) ;
135+ }
130136 }
137+ }
131138 else {
132139 manager . SaveStrongReference ( manager . Owner . UpdateState ( key , tuple ) ) ;
133140 entityKeys . Add ( key ) ;
134- if ( areToNotifyAboutKeys )
141+ if ( areToNotifyAboutKeys ) {
135142 referencingFieldDescriptor . NotifySubscriber ( ownerKey , key ) ;
143+ }
136144 }
137145 }
138146 }
139- manager . Owner . UpdateState ( ownerKey , ReferencingField ,
140- ItemCountLimit == null || entityKeys . Count < ItemCountLimit , entityKeys , auxEntities ) ;
147+ var updatedState = manager . Owner . UpdateState ( ownerKey , ReferencingField ,
148+ ItemCountLimit == null || entityKeys . Count < ItemCountLimit , entityKeys , auxEntities ) ;
149+ if ( updatedState != null ) {
150+ updatedState . SetLastManualPrefetchId ( referencingFieldDescriptor . PrefetchOperationId ) ;
151+ }
141152 }
142153
143154 public bool Equals ( EntitySetTask other )
144155 {
145- if ( ReferenceEquals ( null , other ) )
156+ if ( ReferenceEquals ( null , other ) ) {
146157 return false ;
147- if ( ReferenceEquals ( this , other ) )
158+ }
159+ if ( ReferenceEquals ( this , other ) ) {
148160 return true ;
161+ }
149162 return other . cacheKey . Equals ( cacheKey ) ;
150163 }
151164
152165 public override bool Equals ( object obj )
153166 {
154- if ( ReferenceEquals ( null , obj ) )
167+ if ( ReferenceEquals ( null , obj ) ) {
155168 return false ;
156- if ( ReferenceEquals ( this , obj ) )
169+ }
170+ if ( ReferenceEquals ( this , obj ) ) {
157171 return true ;
158- if ( obj . GetType ( ) != typeof ( EntitySetTask ) )
172+ }
173+ if ( obj . GetType ( ) != typeof ( EntitySetTask ) ) {
159174 return false ;
175+ }
160176 return Equals ( ( EntitySetTask ) obj ) ;
161177 }
162178
163- public override int GetHashCode ( )
164- {
165- return cacheKey . GetHashCode ( ) ;
166- }
179+ public override int GetHashCode ( ) => cacheKey . GetHashCode ( ) ;
167180
168181 #region Private / internal methods
169182
@@ -172,8 +185,9 @@ private QueryTask CreateQueryTask()
172185 var parameterContext = new ParameterContext ( ) ;
173186 using ( parameterContext . Activate ( ) ) {
174187 ownerParameter . Value = ownerKey . Value ;
175- if ( ItemCountLimit != null )
188+ if ( ItemCountLimit != null ) {
176189 itemCountLimitParameter . Value = ItemCountLimit . Value ;
190+ }
177191 object key = new Pair < object , CacheKey > ( itemsQueryCachingRegion , cacheKey ) ;
178192 Func < object , object > generator = CreateRecordSetLoadingItems ;
179193 var session = manager . Owner . Session ;
@@ -190,14 +204,13 @@ private static CompilableProvider CreateRecordSetLoadingItems(object cachingKey)
190204 var primaryTargetIndex = association . TargetType . Indexes . PrimaryIndex ;
191205 var resultColumns = new List < int > ( primaryTargetIndex . Columns . Count ) ;
192206 ParameterExpression tupleParameter ;
193- CompilableProvider result ;
194- if ( association . AuxiliaryType == null )
195- result = CreateQueryForDirectAssociation ( pair , primaryTargetIndex , resultColumns ) ;
196- else
197- result = CreateQueryForAssociationViaAuxType ( pair , primaryTargetIndex , resultColumns ) ;
207+ var result = association . AuxiliaryType == null
208+ ? CreateQueryForDirectAssociation ( pair , primaryTargetIndex , resultColumns )
209+ : CreateQueryForAssociationViaAuxType ( pair , primaryTargetIndex , resultColumns ) ;
198210 result = result . Select ( resultColumns . ToArray ( ) ) ;
199- if ( pair . Second . ItemCountLimit != null )
211+ if ( pair . Second . ItemCountLimit != null ) {
200212 result = result . Take ( ( ) => itemCountLimitParameter . Value ) ;
213+ }
201214 return result ;
202215 }
203216
@@ -236,26 +249,31 @@ private static CompilableProvider CreateQueryForDirectAssociation(Pair<object, C
236249 private static void AddResultColumnIndexes ( ICollection < int > indexes , IndexInfo index ,
237250 int columnIndexOffset )
238251 {
239- for ( int i = 0 ; i < index . Columns . Count ; i ++ ) {
252+ for ( var i = 0 ; i < index . Columns . Count ; i ++ ) {
240253 var column = index . Columns [ i ] ;
241- if ( PrefetchHelper . IsFieldToBeLoadedByDefault ( column . Field ) )
254+ if ( PrefetchHelper . IsFieldToBeLoadedByDefault ( column . Field ) ) {
242255 indexes . Add ( i + columnIndexOffset ) ;
256+ }
243257 }
244258 }
245259
246260 private static Pair < int > [ ] GetJoiningColumnIndexes ( IndexInfo primaryIndex , IndexInfo associationIndex , bool hasAuxType )
247261 {
248262 var joiningColumns = new Pair < int > [ primaryIndex . KeyColumns . Count ] ;
249263 var firstColumnIndex = primaryIndex . Columns . IndexOf ( primaryIndex . KeyColumns [ 0 ] . Key ) ;
250- for ( int i = 0 ; i < joiningColumns . Length ; i ++ )
251- if ( hasAuxType )
264+ for ( var i = 0 ; i < joiningColumns . Length ; i ++ ) {
265+ if ( hasAuxType ) {
252266 joiningColumns [ i ] =
253267 new Pair < int > ( associationIndex . Columns . IndexOf ( associationIndex . ValueColumns [ i ] ) ,
254268 firstColumnIndex + i ) ;
255- else
269+ }
270+ else {
256271 joiningColumns [ i ] =
257272 new Pair < int > ( associationIndex . Columns . IndexOf ( primaryIndex . KeyColumns [ i ] . Key ) ,
258273 firstColumnIndex + i ) ;
274+ }
275+ }
276+
259277 return joiningColumns ;
260278 }
261279
0 commit comments