diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index 5c67ef9d5b..f4e49c1ccb 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -585,6 +585,9 @@
Microsoft\Data\SqlClient\SqlCommand.NonQuery.cs
+
+ Microsoft\Data\SqlClient\SqlCommand.Reader.cs
+
Microsoft\Data\SqlClient\SqlCommand.Scalar.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.netcore.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.netcore.cs
index ab0d672226..1de6ca10b5 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.netcore.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.netcore.cs
@@ -31,33 +31,6 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
{
private const int MaxRPCNameLength = 1046;
- internal sealed class ExecuteReaderAsyncCallContext : AAsyncCallContext
- {
- public Guid OperationID;
- public CommandBehavior CommandBehavior;
-
- public SqlCommand Command => _owner;
- public TaskCompletionSource TaskCompletionSource => _source;
-
- public void Set(SqlCommand command, TaskCompletionSource source, CancellationTokenRegistration disposable, CommandBehavior behavior, Guid operationID)
- {
- base.Set(command, source, disposable);
- CommandBehavior = behavior;
- OperationID = operationID;
- }
-
- protected override void Clear()
- {
- OperationID = default;
- CommandBehavior = default;
- }
-
- protected override void AfterCleared(SqlCommand owner)
- {
- owner?.SetCachedCommandExecuteReaderAsyncContext(this);
- }
- }
-
///
/// Indicates if the column encryption setting was set at-least once in the batch rpc mode, when using AddBatchCommand.
///
@@ -481,17 +454,6 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}
- private SqlDataReader RunExecuteReaderWithRetry(
- CommandBehavior cmdBehavior,
- RunBehavior runBehavior,
- bool returnStream,
- [CallerMemberName] string method = "")
- {
- return RetryLogicProvider.Execute(
- this,
- () => RunExecuteReader(cmdBehavior, runBehavior, returnStream, method));
- }
-
private void VerifyEndExecuteState(Task completionTask, string endMethod, bool fullCheckForColumnEncryption = false)
{
Debug.Assert(completionTask != null);
@@ -582,322 +544,6 @@ private void ThrowIfReconnectionHasBeenCanceled()
}
}
- ///
- public IAsyncResult BeginExecuteReader() =>
- BeginExecuteReader(callback: null, stateObject: null, CommandBehavior.Default);
-
- ///
- public IAsyncResult BeginExecuteReader(AsyncCallback callback, object stateObject) =>
- BeginExecuteReader(callback, stateObject, CommandBehavior.Default);
-
- ///
- public IAsyncResult BeginExecuteReader(CommandBehavior behavior) =>
- BeginExecuteReader(callback: null, stateObject: null, behavior);
-
- ///
- public IAsyncResult BeginExecuteReader(AsyncCallback callback, object stateObject, CommandBehavior behavior)
- {
- SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.BeginExecuteReader | API | Correlation | Object Id {0}, Behavior {1}, Activity Id {2}, Client Connection Id {3}, Command Text '{4}'", ObjectID, (int)behavior, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
- return BeginExecuteReaderInternal(behavior, callback, stateObject, 0, isRetry: false);
- }
-
- ///
- protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
- {
- SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.ExecuteDbDataReader | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
- return ExecuteReader(behavior);
- }
-
- ///
- new public SqlDataReader ExecuteReader()
- {
- SqlStatistics statistics = null;
- SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.ExecuteReader | API | Correlation | ObjectID {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
- try
- {
- statistics = SqlStatistics.StartTimer(Statistics);
- return ExecuteReader(CommandBehavior.Default);
- }
- finally
- {
- SqlStatistics.StopTimer(statistics);
- }
- }
-
- ///
- new public SqlDataReader ExecuteReader(CommandBehavior behavior)
- {
- // Reset _pendingCancel upon entry into any Execute - used to synchronize state
- // between entry into Execute* API and the thread obtaining the stateObject.
- _pendingCancel = false;
-
- SqlStatistics statistics = null;
- bool success = false;
- int? sqlExceptionNumber = null;
- Exception e = null;
- Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction);
-
- using (TryEventScope.Create("SqlCommand.ExecuteReader | API | Object Id {0}", ObjectID))
- {
- try
- {
- WriteBeginExecuteEvent();
- statistics = SqlStatistics.StartTimer(Statistics);
- return IsProviderRetriable ?
- RunExecuteReaderWithRetry(behavior, RunBehavior.ReturnImmediately, returnStream: true) :
- RunExecuteReader(behavior, RunBehavior.ReturnImmediately, returnStream: true);
- }
- catch (Exception ex)
- {
- if (ex is SqlException sqlException)
- {
- sqlExceptionNumber = sqlException.Number;
- }
-
- e = ex;
- throw;
- }
- finally
- {
- SqlStatistics.StopTimer(statistics);
- WriteEndExecuteEvent(success, sqlExceptionNumber, synchronous: true);
- if (e != null)
- {
- s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e);
- }
- else
- {
- s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction);
- }
- }
- }
- }
-
- ///
- public SqlDataReader EndExecuteReader(IAsyncResult asyncResult)
- {
- try
- {
- return EndExecuteReaderInternal(asyncResult);
- }
- finally
- {
- SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.EndExecuteReader | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
- }
- }
-
- private SqlDataReader EndExecuteReaderAsync(IAsyncResult asyncResult)
- {
- SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.EndExecuteReaderAsync | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
- Debug.Assert(!_internalEndExecuteInitiated || _stateObj == null);
-
- Exception asyncException = ((Task)asyncResult).Exception;
- if (asyncException != null)
- {
- CachedAsyncState?.ResetAsyncState();
- ReliablePutStateObject();
- throw asyncException.InnerException;
- }
- else
- {
- ThrowIfReconnectionHasBeenCanceled();
- // lock on _stateObj prevents races with close/cancel.
- if (!_internalEndExecuteInitiated)
- {
- lock (_stateObj)
- {
- return EndExecuteReaderInternal(asyncResult);
- }
- }
- else
- {
- return EndExecuteReaderInternal(asyncResult);
- }
- }
- }
-
- private SqlDataReader EndExecuteReaderInternal(IAsyncResult asyncResult)
- {
- SqlClientEventSource.Log.TryTraceEvent("SqlCommand.EndExecuteReaderInternal | API | ObjectId {0}, Client Connection Id {1}, MARS={2}, AsyncCommandInProgress={3}",
- _activeConnection?.ObjectID, _activeConnection?.ClientConnectionId,
- _activeConnection?.Parser?.MARSOn, _activeConnection?.AsyncCommandInProgress);
- SqlStatistics statistics = null;
- bool success = false;
- int? sqlExceptionNumber = null;
- try
- {
- success = true;
- statistics = SqlStatistics.StartTimer(Statistics);
- return InternalEndExecuteReader(asyncResult, false, nameof(EndExecuteReader));
- }
- catch (Exception e)
- {
- if (e is SqlException)
- {
- SqlException exception = (SqlException)e;
- sqlExceptionNumber = exception.Number;
- }
-
- if (CachedAsyncState != null)
- {
- CachedAsyncState.ResetAsyncState();
- };
- if (ADP.IsCatchableExceptionType(e))
- {
- ReliablePutStateObject();
- };
- throw;
- }
- finally
- {
- SqlStatistics.StopTimer(statistics);
- WriteEndExecuteEvent(success, sqlExceptionNumber, synchronous: false);
- }
- }
-
- private void CleanupExecuteReaderAsync(Task task, TaskCompletionSource source, Guid operationId)
- {
- if (task.IsFaulted)
- {
- Exception e = task.Exception.InnerException;
- if (!_parentOperationStarted)
- {
- s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e);
- }
- source.SetException(e);
- }
- else
- {
- if (!_parentOperationStarted)
- {
- s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction);
- }
- if (task.IsCanceled)
- {
- source.SetCanceled();
- }
- else
- {
- source.SetResult(task.Result);
- }
- }
- }
-
- private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool isRetry, bool asyncWrite = false)
- {
- TaskCompletionSource