From d6051e201ed5c54955011ca9aa22e0af31de03eb Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 20 Jul 2023 01:05:44 +0100 Subject: [PATCH 1/4] use cached async context object and static delegates for ExecuteNonQueryAsync --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 74 +++++++++++-------- .../Data/SqlClient/SqlInternalConnection.cs | 1 + 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index c2b1f6fa91..e415589ef7 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -93,7 +93,7 @@ protected override void Clear() protected override void AfterCleared(SqlCommand owner) { - + owner?.SetCachedCommandExecuteNonQueryAsyncContext(this); } } @@ -2597,41 +2597,27 @@ private Task InternalExecuteNonQueryAsync(CancellationToken cancellationTok try { Task.Factory.FromAsync( - static (AsyncCallback callback, object stateObject) => ((ExecuteNonQueryAsyncCallContext)stateObject).Command.BeginExecuteNonQueryAsync(callback, stateObject), - static (IAsyncResult result) => ((ExecuteNonQueryAsyncCallContext)result.AsyncState).Command.EndExecuteNonQueryAsync(result), + beginMethod: static (AsyncCallback callback, object stateObject) => // with c# 10/NET6 add [StackTraceHidden] to this + { + return ((ExecuteNonQueryAsyncCallContext)stateObject).Command.BeginExecuteNonQueryAsync(callback, stateObject); + }, + endMethod: static (IAsyncResult asyncResult) => // with c# 10/NET6 add [StackTraceHidden] to this + { + return ((ExecuteNonQueryAsyncCallContext)asyncResult.AsyncState).Command.EndExecuteNonQueryAsync(asyncResult); + }, state: context - ).ContinueWith( - static (Task task, object state) => + ) + .ContinueWith( + static (Task task) => // with c# 10/NET6 add [StackTraceHidden] to this { - ExecuteNonQueryAsyncCallContext context = (ExecuteNonQueryAsyncCallContext)state; - - Guid operationId = context.OperationID; + ExecuteNonQueryAsyncCallContext context = (ExecuteNonQueryAsyncCallContext)task.AsyncState; SqlCommand command = context.Command; + Guid operationId = context.OperationID; TaskCompletionSource source = context.TaskCompletionSource; - context.Dispose(); - context = null; - if (task.IsFaulted) - { - Exception e = task.Exception.InnerException; - s_diagnosticListener.WriteCommandError(operationId, command, command._transaction, e); - source.SetException(e); - } - else - { - if (task.IsCanceled) - { - source.SetCanceled(); - } - else - { - source.SetResult(task.Result); - } - s_diagnosticListener.WriteCommandAfter(operationId, command, command._transaction); - } + command.CleanupAfterExecuteNonQueryAsync(task, source, operationId); }, - state: context, scheduler: TaskScheduler.Default ); } @@ -2645,6 +2631,28 @@ private Task InternalExecuteNonQueryAsync(CancellationToken cancellationTok return returnedTask; } + private void CleanupAfterExecuteNonQueryAsync(Task task, TaskCompletionSource source, Guid operationId) + { + if (task.IsFaulted) + { + Exception e = task.Exception.InnerException; + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); + source.SetException(e); + } + else + { + if (task.IsCanceled) + { + source.SetCanceled(); + } + else + { + source.SetResult(task.Result); + } + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); + } + } + /// protected override Task ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) { @@ -2763,6 +2771,14 @@ private void SetCachedCommandExecuteReaderAsyncContext(ExecuteReaderAsyncCallCon } } + private void SetCachedCommandExecuteNonQueryAsyncContext(ExecuteNonQueryAsyncCallContext instance) + { + if (_activeConnection?.InnerConnection is SqlInternalConnection sqlInternalConnection) + { + Interlocked.CompareExchange(ref sqlInternalConnection.CachedCommandExecuteNonQueryAsyncContext, instance, null); + } + } + /// public override Task ExecuteScalarAsync(CancellationToken cancellationToken) => // Do not use retry logic here as internal call to ExecuteReaderAsync handles retry logic. diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs index a6da618583..ff6894c38c 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs @@ -29,6 +29,7 @@ internal abstract class SqlInternalConnection : DbConnectionInternal #if NETCOREAPP || NETSTANDARD internal SqlCommand.ExecuteReaderAsyncCallContext CachedCommandExecuteReaderAsyncContext; + internal SqlCommand.ExecuteNonQueryAsyncCallContext CachedCommandExecuteNonQueryAsyncContext; internal SqlDataReader.Snapshot CachedDataReaderSnapshot; internal SqlDataReader.IsDBNullAsyncCallContext CachedDataReaderIsDBNullContext; internal SqlDataReader.ReadAsyncCallContext CachedDataReaderReadAsyncContext; From c82bd86b3eb48752e64777a149c3e1f11cfc2a0d Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 20 Jul 2023 01:40:18 +0100 Subject: [PATCH 2/4] use cached async context object and static delegates for ExecuteXmlReaderAsync --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 109 ++++++++++++++---- .../Data/SqlClient/SqlInternalConnection.cs | 2 + 2 files changed, 88 insertions(+), 23 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index e415589ef7..c37c6b45d3 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -97,6 +97,30 @@ protected override void AfterCleared(SqlCommand owner) } } + internal sealed class ExecuteXmlReaderAsyncCallContext : AAsyncCallContext + { + public Guid OperationID; + + public SqlCommand Command => _owner; + public TaskCompletionSource TaskCompletionSource => _source; + + public void Set(SqlCommand command, TaskCompletionSource source, CancellationTokenRegistration disposable, Guid operationID) + { + base.Set(command, source, disposable); + OperationID = operationID; + } + + protected override void Clear() + { + OperationID = default; + } + + protected override void AfterCleared(SqlCommand owner) + { + owner?.SetCachedCommandExecuteXmlReaderContext(this); + } + } + private CommandType _commandType; private int? _commandTimeout; private UpdateRowSource _updatedRowSource = UpdateRowSource.Both; @@ -2779,6 +2803,14 @@ private void SetCachedCommandExecuteNonQueryAsyncContext(ExecuteNonQueryAsyncCal } } + private void SetCachedCommandExecuteXmlReaderContext(ExecuteXmlReaderAsyncCallContext instance) + { + if (_activeConnection?.InnerConnection is SqlInternalConnection sqlInternalConnection) + { + Interlocked.CompareExchange(ref sqlInternalConnection.CachedCommandExecuteXmlReaderAsyncContext, instance, null); + } + } + /// public override Task ExecuteScalarAsync(CancellationToken cancellationToken) => // Do not use retry logic here as internal call to ExecuteReaderAsync handles retry logic. @@ -2907,35 +2939,44 @@ private Task InternalExecuteXmlReaderAsync(CancellationToken cancella registration = cancellationToken.Register(s_cancelIgnoreFailure, this); } + ExecuteXmlReaderAsyncCallContext context = null; + if (_activeConnection?.InnerConnection is SqlInternalConnection sqlInternalConnection) + { + context = Interlocked.Exchange(ref sqlInternalConnection.CachedCommandExecuteXmlReaderAsyncContext, null); + } + if (context is null) + { + context = new ExecuteXmlReaderAsyncCallContext(); + } + context.Set(this, source, registration, operationId); + + Task returnedTask = source.Task; try { returnedTask = RegisterForConnectionCloseNotification(returnedTask); - Task.Factory.FromAsync(BeginExecuteXmlReaderAsync, EndExecuteXmlReaderAsync, null) - .ContinueWith((Task task) => + Task.Factory.FromAsync( + beginMethod: static (AsyncCallback callback, object stateObject) => // with c# 10/NET6 add [StackTraceHidden] to this { - registration.Dispose(); - if (task.IsFaulted) - { - Exception e = task.Exception.InnerException; - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); - source.SetException(e); - } - else - { - s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); - if (task.IsCanceled) - { - source.SetCanceled(); - } - else - { - source.SetResult(task.Result); - } - - } - }, + return ((ExecuteXmlReaderAsyncCallContext)stateObject).Command.BeginExecuteXmlReaderAsync(callback, stateObject); + }, + endMethod: static (IAsyncResult asyncResult) => // with c# 10/NET6 add [StackTraceHidden] to this + { + return ((ExecuteXmlReaderAsyncCallContext)asyncResult.AsyncState).Command.EndExecuteXmlReaderAsync(asyncResult); + }, + state: context + ).ContinueWith( + static (Task task) => + { + ExecuteXmlReaderAsyncCallContext context = (ExecuteXmlReaderAsyncCallContext)task.AsyncState; + SqlCommand command = context.Command; + Guid operationId = context.OperationID; + TaskCompletionSource source = context.TaskCompletionSource; + context.Dispose(); + + command.CleanupAfterExecuteXmlReaderAsync(task, source, operationId); + }, TaskScheduler.Default ); } @@ -2948,6 +2989,28 @@ private Task InternalExecuteXmlReaderAsync(CancellationToken cancella return returnedTask; } + private void CleanupAfterExecuteXmlReaderAsync(Task task, TaskCompletionSource source, Guid operationId) + { + if (task.IsFaulted) + { + Exception e = task.Exception.InnerException; + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); + source.SetException(e); + } + else + { + if (task.IsCanceled) + { + source.SetCanceled(); + } + else + { + source.SetResult(task.Result); + } + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); + } + } + /// public void RegisterColumnEncryptionKeyStoreProvidersOnCommand(IDictionary customProviders) { diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs index ff6894c38c..e6faafc405 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs @@ -30,6 +30,8 @@ internal abstract class SqlInternalConnection : DbConnectionInternal #if NETCOREAPP || NETSTANDARD internal SqlCommand.ExecuteReaderAsyncCallContext CachedCommandExecuteReaderAsyncContext; internal SqlCommand.ExecuteNonQueryAsyncCallContext CachedCommandExecuteNonQueryAsyncContext; + internal SqlCommand.ExecuteXmlReaderAsyncCallContext CachedCommandExecuteXmlReaderAsyncContext; + internal SqlDataReader.Snapshot CachedDataReaderSnapshot; internal SqlDataReader.IsDBNullAsyncCallContext CachedDataReaderIsDBNullContext; internal SqlDataReader.ReadAsyncCallContext CachedDataReaderReadAsyncContext; From b594c58d5a895c1cd05ee7cb256d99e25f35f616 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 20 Jul 2023 01:45:43 +0100 Subject: [PATCH 3/4] convert ExecuteReaderAsync to static delegates --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index c37c6b45d3..507c8d1050 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -36,9 +36,6 @@ public sealed partial class SqlCommand : DbCommand, ICloneable private const int MaxRPCNameLength = 1046; internal readonly int ObjectID = Interlocked.Increment(ref _objectTypeCount); private string _commandText; - private static readonly Func s_beginExecuteReaderAsync = BeginExecuteReaderAsyncCallback; - private static readonly Func s_endExecuteReaderAsync = EndExecuteReaderAsyncCallback; - private static readonly Action> s_cleanupExecuteReaderAsync = CleanupExecuteReaderAsyncCallback; private static readonly Func s_internalEndExecuteNonQuery = InternalEndExecuteNonQueryCallback; private static readonly Func s_internalEndExecuteReader = InternalEndExecuteReaderCallback; private static readonly Func s_beginExecuteReaderInternal = BeginExecuteReaderInternalCallback; @@ -2203,29 +2200,6 @@ private void CleanupExecuteReaderAsync(Task task, TaskCompletionS } } - private static IAsyncResult BeginExecuteReaderAsyncCallback(AsyncCallback callback, object stateObject) - { - ExecuteReaderAsyncCallContext args = (ExecuteReaderAsyncCallContext)stateObject; - return args.Command.BeginExecuteReaderInternal(args.CommandBehavior, callback, stateObject, args.Command.CommandTimeout, inRetry: false, asyncWrite: true); - } - - private static SqlDataReader EndExecuteReaderAsyncCallback(IAsyncResult asyncResult) - { - ExecuteReaderAsyncCallContext args = (ExecuteReaderAsyncCallContext)asyncResult.AsyncState; - return args.Command.EndExecuteReaderAsync(asyncResult); - } - - private static void CleanupExecuteReaderAsyncCallback(Task task) - { - ExecuteReaderAsyncCallContext context = (ExecuteReaderAsyncCallContext)task.AsyncState; - SqlCommand command = context.Command; - Guid operationId = context.OperationID; - TaskCompletionSource source = context.TaskCompletionSource; - context.Dispose(); - - command.CleanupExecuteReaderAsync(task, source, operationId); - } - private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite = false) { TaskCompletionSource globalCompletion = new TaskCompletionSource(stateObject); @@ -2765,12 +2739,29 @@ private Task InternalExecuteReaderAsync(CommandBehavior behavior, context.Set(this, source, registration, behavior, operationId); Task.Factory.FromAsync( - beginMethod: s_beginExecuteReaderAsync, - endMethod: s_endExecuteReaderAsync, + beginMethod: static (AsyncCallback callback, object stateObject) => + { + ExecuteReaderAsyncCallContext args = (ExecuteReaderAsyncCallContext)stateObject; + return args.Command.BeginExecuteReaderInternal(args.CommandBehavior, callback, stateObject, args.Command.CommandTimeout, inRetry: false, asyncWrite: true); + }, + endMethod: static (IAsyncResult asyncResult) => + { + ExecuteReaderAsyncCallContext args = (ExecuteReaderAsyncCallContext)asyncResult.AsyncState; + return args.Command.EndExecuteReaderAsync(asyncResult); + }, state: context ).ContinueWith( - continuationAction: s_cleanupExecuteReaderAsync, - TaskScheduler.Default + continuationAction: static (Task task) => + { + ExecuteReaderAsyncCallContext context = (ExecuteReaderAsyncCallContext)task.AsyncState; + SqlCommand command = context.Command; + Guid operationId = context.OperationID; + TaskCompletionSource source = context.TaskCompletionSource; + context.Dispose(); + + command.CleanupExecuteReaderAsync(task, source, operationId); + }, + scheduler: TaskScheduler.Default ); } catch (Exception e) From 2e1fd2a533cfc8286640f313ef7343a398c85c58 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 20 Jul 2023 01:59:02 +0100 Subject: [PATCH 4/4] replaced manually cached delegates with static lambdas --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 114 ++++++++++-------- 1 file changed, 66 insertions(+), 48 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index 507c8d1050..3e12b61a61 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -36,12 +36,6 @@ public sealed partial class SqlCommand : DbCommand, ICloneable private const int MaxRPCNameLength = 1046; internal readonly int ObjectID = Interlocked.Increment(ref _objectTypeCount); private string _commandText; - private static readonly Func s_internalEndExecuteNonQuery = InternalEndExecuteNonQueryCallback; - private static readonly Func s_internalEndExecuteReader = InternalEndExecuteReaderCallback; - private static readonly Func s_beginExecuteReaderInternal = BeginExecuteReaderInternalCallback; - private static readonly Func s_beginExecuteXmlReaderInternal = BeginExecuteXmlReaderInternalCallback; - private static readonly Func s_beginExecuteNonQueryInternal = BeginExecuteNonQueryInternalCallback; - internal sealed class ExecuteReaderAsyncCallContext : AAsyncCallContext { public Guid OperationID; @@ -1328,7 +1322,27 @@ private IAsyncResult BeginExecuteNonQueryInternal(CommandBehavior behavior, Asyn // When we use query caching for parameter encryption we need to retry on specific errors. // In these cases finalize the call internally and trigger a retry when needed. - if (!TriggerInternalEndAndRetryIfNecessary(behavior, stateObject, timeout, usedCache, inRetry, asyncWrite, globalCompletion, localCompletion, s_internalEndExecuteNonQuery, s_beginExecuteNonQueryInternal, nameof(EndExecuteNonQuery))) + if ( + !TriggerInternalEndAndRetryIfNecessary( + behavior, + stateObject, + timeout, + usedCache, + inRetry, + asyncWrite, + globalCompletion, + localCompletion, + endFunc: static (SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) => + { + return command.InternalEndExecuteNonQuery(asyncResult, isInternal, endMethod); + }, + retryFunc: static (SqlCommand command, CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite) => + { + return command.BeginExecuteNonQueryInternal(behavior, callback, stateObject, timeout, inRetry, asyncWrite); + }, + nameof(EndExecuteNonQuery) + ) + ) { globalCompletion = localCompletion; } @@ -1337,7 +1351,7 @@ private IAsyncResult BeginExecuteNonQueryInternal(CommandBehavior behavior, Asyn if (callback != null) { globalCompletion.Task.ContinueWith( - static (task, state) => ((AsyncCallback)state)(task), + static (Task task, object state) => ((AsyncCallback)state)(task), state: callback ); } @@ -1838,7 +1852,27 @@ private IAsyncResult BeginExecuteXmlReaderInternal(CommandBehavior behavior, Asy // When we use query caching for parameter encryption we need to retry on specific errors. // In these cases finalize the call internally and trigger a retry when needed. - if (!TriggerInternalEndAndRetryIfNecessary(behavior, stateObject, timeout, usedCache, inRetry, asyncWrite, globalCompletion, localCompletion, s_internalEndExecuteReader, s_beginExecuteXmlReaderInternal, endMethod: nameof(EndExecuteXmlReader))) + if ( + !TriggerInternalEndAndRetryIfNecessary( + behavior, + stateObject, + timeout, + usedCache, + inRetry, + asyncWrite, + globalCompletion, + localCompletion, + endFunc: static (SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) => + { + return command.InternalEndExecuteReader(asyncResult, isInternal, endMethod); + }, + retryFunc: static (SqlCommand command, CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite) => + { + return command.BeginExecuteXmlReaderInternal(behavior, callback, stateObject, timeout, inRetry, asyncWrite); + }, + endMethod: nameof(EndExecuteXmlReader) + ) + ) { globalCompletion = localCompletion; } @@ -1847,7 +1881,7 @@ private IAsyncResult BeginExecuteXmlReaderInternal(CommandBehavior behavior, Asy if (callback != null) { localCompletion.Task.ContinueWith( - static (task, state) => ((AsyncCallback)state)(task), + static (Task task, object state) => ((AsyncCallback)state)(task), state: callback ); } @@ -2264,7 +2298,27 @@ private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncC // When we use query caching for parameter encryption we need to retry on specific errors. // In these cases finalize the call internally and trigger a retry when needed. - if (!TriggerInternalEndAndRetryIfNecessary(behavior, stateObject, timeout, usedCache, inRetry, asyncWrite, globalCompletion, localCompletion, s_internalEndExecuteReader, s_beginExecuteReaderInternal, nameof(EndExecuteReader))) + if ( + !TriggerInternalEndAndRetryIfNecessary( + behavior, + stateObject, + timeout, + usedCache, + inRetry, + asyncWrite, + globalCompletion, + localCompletion, + endFunc: static (SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) => + { + return command.InternalEndExecuteReader(asyncResult, isInternal, endMethod); + }, + retryFunc: static (SqlCommand command, CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite) => + { + return command.BeginExecuteReaderInternal(behavior, callback, stateObject, timeout, inRetry, asyncWrite); + }, + nameof(EndExecuteReader) + ) + ) { globalCompletion = localCompletion; } @@ -2273,7 +2327,7 @@ private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncC if (callback != null) { globalCompletion.Task.ContinueWith( - static (task, state) => ((AsyncCallback)state)(task), + static (Task task, object state) => ((AsyncCallback)state)(task), state: callback ); } @@ -2286,42 +2340,6 @@ private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncC } } - /// - /// used to convert an invocation through a cached static delegate back to an instance call - /// - private static SqlDataReader InternalEndExecuteReaderCallback(SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) - { - return command.InternalEndExecuteReader(asyncResult, isInternal, endMethod); - } - /// - /// used to convert an invocation through a cached static delegate back to an instance call - /// - private static IAsyncResult BeginExecuteReaderInternalCallback(SqlCommand command, CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite) - { - return command.BeginExecuteReaderInternal(behavior, callback, stateObject, timeout, inRetry, asyncWrite); - } - /// - /// used to convert an invocation through a cached static delegate back to an instance call - /// - private static IAsyncResult BeginExecuteXmlReaderInternalCallback(SqlCommand command, CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite) - { - return command.BeginExecuteXmlReaderInternal(behavior, callback, stateObject, timeout, inRetry, asyncWrite); - } - /// - /// used to convert an invocation through a cached static delegate back to an instance call - /// - private static object InternalEndExecuteNonQueryCallback(SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) - { - return command.InternalEndExecuteNonQuery(asyncResult, isInternal, endMethod); - } - /// - /// used to convert an invocation through a cached static delegate back to an instance call - /// - private static IAsyncResult BeginExecuteNonQueryInternalCallback(SqlCommand command, CommandBehavior behavior, AsyncCallback callback, object stateObject, int timeout, bool inRetry, bool asyncWrite) - { - return command.BeginExecuteNonQueryInternal(behavior, callback, stateObject, timeout, inRetry, asyncWrite); - } - private bool TriggerInternalEndAndRetryIfNecessary( CommandBehavior behavior, object stateObject,