Skip to content

Commit 37d8a3f

Browse files
authored
Merge | SqlCommand Scalar Methods (#3619)
* Create partial file for Scalar execution * Merge ExecuteScalar * Merge CompleteExecuteScalar * Merge ExecuteScalarAsync * Merge InternalExecuteScalarAsync => ExecuteScalarAsyncInternal * Merge ExecuteScalarBatchAsync * Migrate ExecuteScalarUntilEndAsync * Addressing @edwardneal's comments: * Restore comment re: async untyped value getter * Flip order of correlation event and trace event * Introduce netfx style of result, success, return * Adding <content> tags to the partials
1 parent 94a51da commit 37d8a3f

File tree

6 files changed

+368
-396
lines changed

6 files changed

+368
-396
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@
582582
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.cs">
583583
<Link>Microsoft\Data\SqlClient\SqlCommand.cs</Link>
584584
</Compile>
585+
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.Scalar.cs">
586+
<Link>Microsoft\Data\SqlClient\SqlCommand.Scalar.cs</Link>
587+
</Compile>
585588
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommandSet.cs">
586589
<Link>Microsoft\Data\SqlClient\SqlCommandSet.cs</Link>
587590
</Compile>

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.netcore.cs

Lines changed: 0 additions & 248 deletions
Original file line numberDiff line numberDiff line change
@@ -539,74 +539,6 @@ private SqlDataReader RunExecuteReaderWithRetry(
539539
() => RunExecuteReader(cmdBehavior, runBehavior, returnStream, method));
540540
}
541541

542-
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteScalar/*'/>
543-
public override object ExecuteScalar()
544-
{
545-
// Reset _pendingCancel upon entry into any Execute - used to synchronize state
546-
// between entry into Execute* API and the thread obtaining the stateObject.
547-
_pendingCancel = false;
548-
549-
using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction))
550-
using (TryEventScope.Create("SqlCommand.ExecuteScalar | API | ObjectId {0}", ObjectID))
551-
{
552-
SqlStatistics statistics = null;
553-
bool success = false;
554-
int? sqlExceptionNumber = null;
555-
SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.ExecuteScalar | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
556-
557-
try
558-
{
559-
statistics = SqlStatistics.StartTimer(Statistics);
560-
WriteBeginExecuteEvent();
561-
SqlDataReader ds = IsProviderRetriable
562-
? RunExecuteReaderWithRetry(0, RunBehavior.ReturnImmediately, returnStream: true)
563-
: RunExecuteReader(0, RunBehavior.ReturnImmediately, returnStream: true);
564-
success = true;
565-
return CompleteExecuteScalar(ds, _batchRPCMode);
566-
}
567-
catch (Exception ex)
568-
{
569-
diagnosticScope.SetException(ex);
570-
if (ex is SqlException sqlException)
571-
{
572-
sqlExceptionNumber = sqlException.Number;
573-
}
574-
throw;
575-
}
576-
finally
577-
{
578-
SqlStatistics.StopTimer(statistics);
579-
WriteEndExecuteEvent(success, sqlExceptionNumber, synchronous: true);
580-
}
581-
}
582-
}
583-
584-
private object CompleteExecuteScalar(SqlDataReader ds, bool returnLastResult)
585-
{
586-
object retResult = null;
587-
588-
try
589-
{
590-
do
591-
{
592-
if (ds.Read())
593-
{
594-
if (ds.FieldCount > 0)
595-
{
596-
retResult = ds.GetValue(0);
597-
}
598-
}
599-
} while (returnLastResult && ds.NextResult());
600-
}
601-
finally
602-
{
603-
// clean off the wire
604-
ds.Close();
605-
}
606-
607-
return retResult;
608-
}
609-
610542
private Task InternalExecuteNonQueryWithRetry(
611543
bool sendToPipe,
612544
int timeout,
@@ -2291,186 +2223,6 @@ private void SetCachedCommandExecuteXmlReaderContext(ExecuteXmlReaderAsyncCallCo
22912223
}
22922224
}
22932225

2294-
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteScalarAsync[@name="CancellationToken"]/*'/>
2295-
public override Task<object> ExecuteScalarAsync(CancellationToken cancellationToken) =>
2296-
// Do not use retry logic here as internal call to ExecuteReaderAsync handles retry logic.
2297-
InternalExecuteScalarAsync(cancellationToken);
2298-
2299-
private Task<object> InternalExecuteScalarAsync(CancellationToken cancellationToken)
2300-
{
2301-
SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.InternalExecuteScalarAsync | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
2302-
SqlClientEventSource.Log.TryTraceEvent("SqlCommand.InternalExecuteScalarAsync | API> {0}, Client Connection Id {1}, Command Text = '{2}'", ObjectID, Connection?.ClientConnectionId, CommandText);
2303-
_parentOperationStarted = true;
2304-
Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction);
2305-
2306-
return ExecuteReaderAsync(cancellationToken).ContinueWith((executeTask) =>
2307-
{
2308-
TaskCompletionSource<object> source = new TaskCompletionSource<object>();
2309-
if (executeTask.IsCanceled)
2310-
{
2311-
source.SetCanceled();
2312-
}
2313-
else if (executeTask.IsFaulted)
2314-
{
2315-
s_diagnosticListener.WriteCommandError(operationId, this, _transaction, executeTask.Exception.InnerException);
2316-
source.SetException(executeTask.Exception.InnerException);
2317-
}
2318-
else
2319-
{
2320-
SqlDataReader reader = executeTask.Result;
2321-
reader.ReadAsync(cancellationToken)
2322-
.ContinueWith((Task<bool> readTask) =>
2323-
{
2324-
try
2325-
{
2326-
if (readTask.IsCanceled)
2327-
{
2328-
reader.Dispose();
2329-
source.SetCanceled();
2330-
}
2331-
else if (readTask.IsFaulted)
2332-
{
2333-
reader.Dispose();
2334-
s_diagnosticListener.WriteCommandError(operationId, this, _transaction, readTask.Exception.InnerException);
2335-
source.SetException(readTask.Exception.InnerException);
2336-
}
2337-
else
2338-
{
2339-
Exception exception = null;
2340-
object result = null;
2341-
try
2342-
{
2343-
bool more = readTask.Result;
2344-
if (more && reader.FieldCount > 0)
2345-
{
2346-
try
2347-
{
2348-
result = reader.GetValue(0);
2349-
}
2350-
catch (Exception e)
2351-
{
2352-
exception = e;
2353-
}
2354-
}
2355-
}
2356-
finally
2357-
{
2358-
reader.Dispose();
2359-
}
2360-
if (exception != null)
2361-
{
2362-
s_diagnosticListener.WriteCommandError(operationId, this, _transaction, exception);
2363-
source.SetException(exception);
2364-
}
2365-
else
2366-
{
2367-
s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction);
2368-
source.SetResult(result);
2369-
}
2370-
}
2371-
}
2372-
catch (Exception e)
2373-
{
2374-
// exception thrown by Dispose...
2375-
source.SetException(e);
2376-
}
2377-
},
2378-
TaskScheduler.Default
2379-
);
2380-
}
2381-
_parentOperationStarted = false;
2382-
return source.Task;
2383-
}, TaskScheduler.Default).Unwrap();
2384-
}
2385-
2386-
internal Task<object> ExecuteScalarBatchAsync(CancellationToken cancellationToken)
2387-
{
2388-
_parentOperationStarted = true;
2389-
Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction);
2390-
2391-
return ExecuteReaderAsync(cancellationToken).ContinueWith((executeTask) =>
2392-
{
2393-
TaskCompletionSource<object> source = new TaskCompletionSource<object>();
2394-
if (executeTask.IsCanceled)
2395-
{
2396-
source.SetCanceled();
2397-
}
2398-
else if (executeTask.IsFaulted)
2399-
{
2400-
s_diagnosticListener.WriteCommandError(operationId, this, _transaction, executeTask.Exception.InnerException);
2401-
source.SetException(executeTask.Exception.InnerException);
2402-
}
2403-
else
2404-
{
2405-
SqlDataReader reader = executeTask.Result;
2406-
ExecuteScalarUntilEndAsync(reader, cancellationToken).ContinueWith(
2407-
(readTask) =>
2408-
{
2409-
try
2410-
{
2411-
if (readTask.IsCanceled)
2412-
{
2413-
reader.Dispose();
2414-
source.SetCanceled();
2415-
}
2416-
else if (readTask.IsFaulted)
2417-
{
2418-
reader.Dispose();
2419-
s_diagnosticListener.WriteCommandError(operationId, this, _transaction, readTask.Exception.InnerException);
2420-
source.SetException(readTask.Exception.InnerException);
2421-
}
2422-
else
2423-
{
2424-
Exception exception = null;
2425-
object result = null;
2426-
try
2427-
{
2428-
result = readTask.Result;
2429-
}
2430-
finally
2431-
{
2432-
reader.Dispose();
2433-
}
2434-
if (exception != null)
2435-
{
2436-
s_diagnosticListener.WriteCommandError(operationId, this, _transaction, exception);
2437-
source.SetException(exception);
2438-
}
2439-
else
2440-
{
2441-
s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction);
2442-
source.SetResult(result);
2443-
}
2444-
}
2445-
}
2446-
catch (Exception e)
2447-
{
2448-
// exception thrown by Dispose...
2449-
source.SetException(e);
2450-
}
2451-
},
2452-
TaskScheduler.Default
2453-
);
2454-
}
2455-
_parentOperationStarted = false;
2456-
return source.Task;
2457-
}, TaskScheduler.Default).Unwrap();
2458-
}
2459-
2460-
private async Task<object> ExecuteScalarUntilEndAsync(SqlDataReader reader, CancellationToken cancellationToken)
2461-
{
2462-
object retval = null;
2463-
do
2464-
{
2465-
if (await reader.ReadAsync(cancellationToken).ConfigureAwait(false) && reader.FieldCount > 0)
2466-
{
2467-
retval = reader.GetValue(0); // no async untyped value getter, this will work ok as long as the value is in the current packet
2468-
}
2469-
}
2470-
while (_batchRPCMode && !cancellationToken.IsCancellationRequested && await reader.NextResultAsync(cancellationToken).ConfigureAwait(false));
2471-
return retval;
2472-
}
2473-
24742226
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteXmlReaderAsync[@name="default"]/*'/>
24752227
public Task<XmlReader> ExecuteXmlReaderAsync() =>
24762228
ExecuteXmlReaderAsync(CancellationToken.None);

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,9 @@
750750
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.cs">
751751
<Link>Microsoft\Data\SqlClient\SqlCommand.cs</Link>
752752
</Compile>
753+
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.Scalar.cs">
754+
<Link>Microsoft\Data\SqlClient\SqlCommand.Scalar.cs</Link>
755+
</Compile>
753756
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommandBuilder.cs">
754757
<Link>Microsoft\Data\SqlClient\SqlCommandBuilder.cs</Link>
755758
</Compile>

0 commit comments

Comments
 (0)