1010using System . Linq ;
1111using System . Threading ;
1212using Xtensive . Caching ;
13+ using Xtensive . Core ;
1314using KeyCache = Xtensive . Caching . ICache < Xtensive . Orm . Key , Xtensive . Orm . Key > ;
1415
1516namespace Xtensive . Orm . Internals
@@ -40,8 +41,8 @@ public BackupedState(EntitySetState state)
4041 private readonly EntitySetBase owner ;
4142 private readonly bool isDisconnected ;
4243
44+ private Guid lastManualPrefetchId ;
4345 private bool isLoaded ;
44-
4546 private long ? totalItemCount ;
4647 private int version ;
4748 private IDictionary < Key , Key > addedKeys ;
@@ -134,10 +135,11 @@ public bool HasChanges
134135 /// <param name="keys">The keys.</param>
135136 public void Update ( IEnumerable < Key > keys , long ? count )
136137 {
137- if ( ! isDisconnected )
138- UpdateStateRegular ( keys , count ) ;
138+
139+ if ( HasChanges )
140+ UpdateCachedState ( keys , count ) ;
139141 else
140- UpdateStateDisconnected ( keys , count ) ;
142+ UpdateSyncedState ( keys , count ) ;
141143 }
142144
143145 /// <summary>
@@ -272,6 +274,34 @@ internal void RemapKeys(KeyMapping mapping)
272274 }
273275 }
274276
277+ internal bool ShouldUseForcePrefetch ( Guid ? currentPrefetchOperation )
278+ {
279+ if ( currentPrefetchOperation . HasValue ) {
280+ if ( currentPrefetchOperation . Value == lastManualPrefetchId )
281+ return false ;
282+ lastManualPrefetchId = currentPrefetchOperation . Value ;
283+ }
284+ if ( isDisconnected )
285+ return true ;
286+ if ( Session . Transaction != null )
287+ switch ( Session . Transaction . Outermost . IsolationLevel ) {
288+ case System . Transactions . IsolationLevel . ReadCommitted :
289+ case System . Transactions . IsolationLevel . ReadUncommitted :
290+ return true ;
291+ case System . Transactions . IsolationLevel . RepeatableRead :
292+ return string . Equals ( Session . Handlers . ProviderInfo . ProviderName , WellKnown . Provider . SqlServer , StringComparison . Ordinal ) ;
293+ default :
294+ return false ;
295+ }
296+ return false ;
297+ }
298+
299+ internal void SetLastManualPrefetchId ( Guid ? prefetchOperationId )
300+ {
301+ if ( prefetchOperationId . HasValue )
302+ lastManualPrefetchId = prefetchOperationId . Value ;
303+ }
304+
275305 /// <inheritdoc/>
276306 protected override void Invalidate ( )
277307 {
@@ -323,7 +353,7 @@ IEnumerator IEnumerable.GetEnumerator()
323353 #endregion
324354
325355
326- private void UpdateStateRegular ( IEnumerable < Key > keys , long ? count )
356+ private void UpdateSyncedState ( IEnumerable < Key > keys , long ? count )
327357 {
328358 FetchedKeys . Clear ( ) ;
329359 TotalItemCount = count ;
@@ -332,19 +362,20 @@ private void UpdateStateRegular(IEnumerable<Key> keys, long? count)
332362 Rebind ( ) ;
333363 }
334364
335- private void UpdateStateDisconnected ( IEnumerable < Key > syncronizedKeys , long ? count )
365+ public void UpdateCachedState ( IEnumerable < Key > keys , long ? count )
336366 {
337367 FetchedKeys . Clear ( ) ;
338- var countExceptRemoved = 0 ;
339- foreach ( var key in syncronizedKeys ) {
368+ var becameRemovedOnSever = removedKeys . Keys . ToHashSet ( ) ;
369+ TotalItemCount = count ;
370+ foreach ( var key in keys ) {
371+ if ( addedKeys . ContainsKey ( key ) )
372+ addedKeys . Remove ( key ) ;
373+ else if ( becameRemovedOnSever . Contains ( key ) )
374+ becameRemovedOnSever . Remove ( key ) ;
340375 FetchedKeys . Add ( key ) ;
341- if ( ! removedKeys . ContainsKey ( key ) )
342- countExceptRemoved ++ ;
343376 }
344- TotalItemCount = count . HasValue
345- ? countExceptRemoved + AddedItemsCount
346- : count ;
347- Rebind ( ) ;
377+ foreach ( var removedOnServer in becameRemovedOnSever )
378+ removedKeys . Remove ( removedOnServer ) ;
348379 }
349380
350381 private void EnsureFetchedKeysIsNotNull ( )
@@ -379,6 +410,7 @@ internal EntitySetState(EntitySetBase entitySet)
379410 owner = entitySet ;
380411 version = int . MinValue ;
381412 isDisconnected = entitySet . Session . IsDisconnected ;
413+ lastManualPrefetchId = Guid . Empty ;
382414 }
383415 }
384416}
0 commit comments