@@ -30,7 +30,7 @@ namespace Microsoft.Data.SqlClient
3030    /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml' path='docs/members[@name="SqlDataReader"]/SqlDataReader/*' /> 
3131    public  class  SqlDataReader  :  DbDataReader ,  IDataReader ,  IDbColumnSchemaGenerator 
3232    { 
33-         private  enum  ALTROWSTATUS 
33+         internal  enum  ALTROWSTATUS 
3434        { 
3535            Null  =  0 ,            // default and after Done 
3636            AltRow ,              // after calling NextResult and the first AltRow is available for read 
@@ -97,9 +97,6 @@ internal class SharedState
9797        private  SqlSequentialStream  _currentStream ; 
9898        private  SqlSequentialTextReader  _currentTextReader ; 
9999
100-         private  IsDBNullAsyncCallContext  _cachedIsDBNullContext ; 
101-         private  ReadAsyncCallContext  _cachedReadAsyncContext ; 
102- 
103100        internal  SqlDataReader ( SqlCommand  command ,  CommandBehavior  behavior ) 
104101        { 
105102            SqlConnection . VerifyExecutePermission ( ) ; 
@@ -4387,6 +4384,10 @@ internal TdsOperationStatus TryReadColumnInternal(int i, bool readHeaderOnly/* =
43874384                { 
43884385                    // reset snapshot to save memory use.  We can safely do that here because all SqlDataReader values are stable. 
43894386                    // The retry logic can use the current values to get back to the right state. 
4387+                     if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection  &&  sqlInternalConnection . CachedDataReaderSnapshot  is  null ) 
4388+                     { 
4389+                         sqlInternalConnection . CachedDataReaderSnapshot  =  _snapshot ; 
4390+                     } 
43904391                    _snapshot  =  null ; 
43914392                    PrepareAsyncInvocation ( useSnapshot :  true ) ; 
43924393                } 
@@ -5318,7 +5319,15 @@ public override Task<bool> ReadAsync(CancellationToken cancellationToken)
53185319                    return  source . Task ; 
53195320                } 
53205321
5321-                 var  context  =  Interlocked . Exchange ( ref  _cachedReadAsyncContext ,  null )  ??  new  ReadAsyncCallContext ( ) ; 
5322+                 ReadAsyncCallContext  context  =  null ; 
5323+                 if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection ) 
5324+                 { 
5325+                     context  =  Interlocked . Exchange ( ref  sqlInternalConnection . CachedDataReaderReadAsyncContext ,  null ) ; 
5326+                 } 
5327+                 if  ( context  is  null ) 
5328+                 { 
5329+                     context  =  new  ReadAsyncCallContext ( ) ; 
5330+                 } 
53225331
53235332                Debug . Assert ( context . Reader  ==  null  &&  context . Source  ==  null  &&  context . Disposable  ==  default ,  "cached ReadAsyncCallContext was not properly disposed" ) ; 
53245333
@@ -5358,6 +5367,10 @@ private static Task<bool> ReadAsyncExecute(Task task, object state)
53585367                    if  ( ! hasReadRowToken ) 
53595368                    { 
53605369                        hasReadRowToken  =  true ; 
5370+                         if  ( reader . Connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection  &&  sqlInternalConnection . CachedDataReaderSnapshot  is  null ) 
5371+                         { 
5372+                             sqlInternalConnection . CachedDataReaderSnapshot  =  reader . _snapshot ; 
5373+                         } 
53615374                        reader . _snapshot  =  null ; 
53625375                        reader . PrepareAsyncInvocation ( useSnapshot :  true ) ; 
53635376                    } 
@@ -5377,7 +5390,10 @@ private static Task<bool> ReadAsyncExecute(Task task, object state)
53775390
53785391        private  void  SetCachedReadAsyncCallContext ( ReadAsyncCallContext  instance ) 
53795392        { 
5380-             Interlocked . CompareExchange ( ref  _cachedReadAsyncContext ,  instance ,  null ) ; 
5393+             if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection ) 
5394+             { 
5395+                 Interlocked . CompareExchange ( ref  sqlInternalConnection . CachedDataReaderReadAsyncContext ,  instance ,  null ) ; 
5396+             } 
53815397        } 
53825398
53835399        /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml' path='docs/members[@name="SqlDataReader"]/IsDBNullAsync/*' /> 
@@ -5479,7 +5495,15 @@ override public Task<bool> IsDBNullAsync(int i, CancellationToken cancellationTo
54795495                        registrationHolder . Set ( cancellationToken . Register ( SqlCommand . s_cancelIgnoreFailure ,  _command ) ) ; 
54805496                    } 
54815497
5482-                     IsDBNullAsyncCallContext  context  =  Interlocked . Exchange ( ref  _cachedIsDBNullContext ,  null )  ??  new  IsDBNullAsyncCallContext ( ) ; 
5498+                     IsDBNullAsyncCallContext  context  =  null ; 
5499+                     if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection ) 
5500+                     { 
5501+                         context  =  Interlocked . Exchange ( ref  sqlInternalConnection . CachedDataReaderIsDBNullContext ,  null ) ; 
5502+                     } 
5503+                     if  ( context  is  null ) 
5504+                     { 
5505+                         context  =  new  IsDBNullAsyncCallContext ( ) ; 
5506+                     } 
54835507
54845508                    Debug . Assert ( context . Reader  ==  null  &&  context . Source  ==  null  &&  context . Disposable  ==  default ,  "cached ISDBNullAsync context not properly disposed" ) ; 
54855509
@@ -5517,7 +5541,10 @@ private static Task<bool> IsDBNullAsyncExecute(Task task, object state)
55175541
55185542        private  void  SetCachedIDBNullAsyncCallContext ( IsDBNullAsyncCallContext  instance ) 
55195543        { 
5520-             Interlocked . CompareExchange ( ref  _cachedIsDBNullContext ,  instance ,  null ) ; 
5544+             if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection ) 
5545+             { 
5546+                 Interlocked . CompareExchange ( ref  sqlInternalConnection . CachedDataReaderIsDBNullContext ,  instance ,  null ) ; 
5547+             } 
55215548        } 
55225549
55235550        /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml' path='docs/members[@name="SqlDataReader"]/GetFieldValueAsync/*' /> 
@@ -6019,7 +6046,7 @@ private void CompleteAsyncCall<T>(Task<T> task, SqlDataReaderBaseAsyncCallContex
60196046            } 
60206047        } 
60216048
6022-         private  sealed  class  Snapshot 
6049+         internal  sealed  class  Snapshot 
60236050        { 
60246051            public  bool  _dataReady ; 
60256052            public  bool  _haltRead ; 
@@ -6051,7 +6078,14 @@ private void PrepareAsyncInvocation(bool useSnapshot)
60516078
60526079                if  ( _snapshot  ==  null ) 
60536080                { 
6054-                     _snapshot  =  new  Snapshot ( ) ; 
6081+                     if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection ) 
6082+                     { 
6083+                         _snapshot  =  Interlocked . Exchange ( ref  sqlInternalConnection . CachedDataReaderSnapshot ,  null )  ??  new  Snapshot ( ) ; 
6084+                     } 
6085+                     else 
6086+                     { 
6087+                         _snapshot  =  new  Snapshot ( ) ; 
6088+                     } 
60556089
60566090                    _snapshot . _dataReady  =  _sharedState . _dataReady ; 
60576091                    _snapshot . _haltRead  =  _haltRead ; 
@@ -6124,6 +6158,10 @@ private void CleanupAfterAsyncInvocationInternal(TdsParserStateObject stateObj,
61246158            stateObj . _permitReplayStackTraceToDiffer  =  false ; 
61256159#endif
61266160
6161+             if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection  &&  sqlInternalConnection . CachedDataReaderSnapshot  is  null ) 
6162+             { 
6163+                 sqlInternalConnection . CachedDataReaderSnapshot  =  _snapshot ; 
6164+             } 
61276165            // We are setting this to null inside the if-statement because stateObj==null means that the reader hasn't been initialized or has been closed (either way _snapshot should already be null) 
61286166            _snapshot  =  null ; 
61296167        } 
@@ -6162,6 +6200,10 @@ private void SwitchToAsyncWithoutSnapshot()
61626200            Debug . Assert ( _snapshot  !=  null ,  "Should currently have a snapshot" ) ; 
61636201            Debug . Assert ( _stateObj  !=  null  &&  ! _stateObj . _asyncReadWithoutSnapshot ,  "Already in async without snapshot" ) ; 
61646202
6203+             if  ( _connection ? . InnerConnection  is  SqlInternalConnection  sqlInternalConnection  &&  sqlInternalConnection . CachedDataReaderSnapshot  is  null ) 
6204+             { 
6205+                 sqlInternalConnection . CachedDataReaderSnapshot  =  _snapshot ; 
6206+             } 
61656207            _snapshot  =  null ; 
61666208            _stateObj . ResetSnapshot ( ) ; 
61676209            _stateObj . _asyncReadWithoutSnapshot  =  true ; 
0 commit comments