diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index f897e55f77..9a8c0cb9f6 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -7,6 +7,7 @@ + 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 d1dd14f6b7..ec18940c2a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -201,62 +201,62 @@ Microsoft\Data\SqlClient\DataClassification\SensitivityClassification.cs - - Microsoft\Data\SqlClient\Diagnostics\DiagnosticScope.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\DiagnosticScope.cs - - Microsoft\Data\SqlClient\Diagnostics\DiagnosticTransactionScope.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\DiagnosticTransactionScope.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandAfter.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandAfter.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandBefore.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandBefore.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandError.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandError.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseAfter.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseAfter.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseBefore.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseBefore.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseError.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseError.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenAfter.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenAfter.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenBefore.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenBefore.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenError.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenError.cs Microsoft\Data\SqlClient\Diagnostics\SqlClientMetrics.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitAfter.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitAfter.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitBefore.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitBefore.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitError.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitError.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackAfter.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackAfter.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackBefore.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackBefore.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackError.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackError.cs - - Microsoft\Data\SqlClient\Diagnostics\SqlDiagnosticListener.netcore.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlDiagnosticListener.cs Microsoft\Data\SqlClient\DisposableTemporaryOnStack.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs index d4f13efd80..7fb6462ddd 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -61,7 +61,7 @@ public sealed partial class SqlConnection : DbConnection, ICloneable private SqlRetryLogicBaseProvider _retryLogicProvider; // diagnostics listener - private static readonly SqlDiagnosticListener s_diagnosticListener = new SqlDiagnosticListener(); + private static readonly SqlDiagnosticListener s_diagnosticListener = new(); // Transient Fault handling flag. This is needed to convey to the downstream mechanism of connection establishment, if Transient Fault handling should be used or not // The downstream handling of Connection open is the same for idle connection resiliency. Currently we want to apply transient fault handling only to the connections opened @@ -1458,8 +1458,8 @@ public void Open(SqlConnectionOverrides overrides) PrepareStatisticsForNewConnection(); SqlStatistics statistics = null; - Exception e = null; + try { statistics = SqlStatistics.StartTimer(Statistics); diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs index a3bb3b46c2..52a05a7fde 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs @@ -1960,6 +1960,417 @@ public sealed class SqlConfigurableRetryFactory public static SqlRetryLogicBaseProvider CreateNoneRetryProvider() { throw null; } } } +namespace Microsoft.Data.SqlClient.Diagnostics +{ + /// + public sealed class SqlClientCommandBefore : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandBefore"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid? ConnectionId => throw null; + /// + public long? TransactionId => throw null; + /// + public SqlCommand Command => throw null; + /// + public int Count => throw null; + /// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientCommandAfter : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandAfter"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid? ConnectionId => throw null; + /// + public long? TransactionId => throw null; + /// + public SqlCommand Command => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// + public int Count => throw null; + /// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientCommandError : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandError"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid? ConnectionId => throw null; + /// + public long? TransactionId => throw null; + /// + public SqlCommand Command => throw null; + /// + public System.Exception Exception { get; } + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientConnectionOpenBefore : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenBefore"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public SqlConnection Connection => throw null; + /// + public string ClientVersion => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientConnectionOpenAfter : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenAfter"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public string ClientVersion => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientConnectionOpenError : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenError"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public string ClientVersion => throw null; + /// + public System.Exception Exception => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientConnectionCloseBefore : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseBefore"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid? ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientConnectionCloseAfter : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseAfter"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid? ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientConnectionCloseError : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseError"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Guid? ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// + public System.Exception Exception => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientTransactionCommitBefore : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitBefore"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientTransactionCommitAfter : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitAfter"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientTransactionCommitError : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitError"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public System.Exception Exception => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientTransactionRollbackBefore : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackBefore"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public string TransactionName => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientTransactionRollbackAfter : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackAfter"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public string TransactionName => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } + /// + public sealed class SqlClientTransactionRollbackError : System.Collections.Generic.IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackError"; + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public string TransactionName => throw null; + /// + public System.Exception Exception => throw null; + /// + public int Count => throw null; + /// >/// + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + } +} namespace Microsoft.Data.SqlClient.Server { /// diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj index 6b507b5a0a..c244a806bf 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj @@ -43,6 +43,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 0c2fe65f93..b2e40438d1 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -336,9 +336,63 @@ Microsoft\Data\SqlClient\ConnectionPool\WaitHandleDbConnectionPool.cs + + Microsoft\Data\SqlClient\Diagnostics\DiagnosticScope.cs + + + Microsoft\Data\SqlClient\Diagnostics\DiagnosticTransactionScope.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandAfter.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandBefore.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientCommandError.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseAfter.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseBefore.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionCloseError.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenAfter.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenBefore.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientConnectionOpenError.cs + Microsoft\Data\SqlClient\Diagnostics\SqlClientMetrics.cs + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitAfter.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitBefore.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionCommitError.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackAfter.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackBefore.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlClientTransactionRollbackError.cs + + + Microsoft\Data\SqlClient\Diagnostics\SqlDiagnosticListener.cs + Microsoft\Data\ProviderBase\DbMetaDataFactory.cs @@ -961,6 +1015,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs index 24cd7dbe28..7990cb041e 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -25,6 +25,7 @@ using Microsoft.Data.Common.ConnectionString; using Microsoft.Data.ProviderBase; using Microsoft.Data.SqlClient.ConnectionPool; +using Microsoft.Data.SqlClient.Diagnostics; using Microsoft.SqlServer.Server; [assembly: InternalsVisibleTo("System.Data.DataSetExtensions, PublicKey=" + Microsoft.Data.SqlClient.AssemblyRef.EcmaPublicKeyFull)] // DevDiv Bugs 92166 @@ -70,6 +71,9 @@ public sealed partial class SqlConnection : DbConnection, ICloneable // Retry Logic private SqlRetryLogicBaseProvider _retryLogicProvider; + // diagnostics listener + private static readonly SqlDiagnosticListener s_diagnosticListener = new(); + // Transient Fault handling flag. This is needed to convey to the downstream mechanism of connection establishment, if Transient Fault handling should be used or not // The downstream handling of Connection open is the same for idle connection resiliency. Currently we want to apply transient fault handling only to the connections opened // using SqlConnection.Open() method. @@ -113,6 +117,8 @@ private static readonly ConcurrentDictionary> _ColumnEncry capacity: 1, comparer: StringComparer.OrdinalIgnoreCase); + private static readonly Action, object> s_openAsyncComplete = OpenAsyncComplete; + private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider); /// @@ -1314,8 +1320,28 @@ public override void Close() { SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current); + ConnectionState previousState = State; + Guid operationId = default(Guid); + Guid clientConnectionId = default(Guid); + + // during the call to Dispose() there is a redundant call to + // Close(). because of this, the second time Close() is invoked the + // connection is already in a closed state. this doesn't seem to be a + // problem except for logging, as we'll get duplicate Before/After/Error + // log entries + if (previousState != ConnectionState.Closed) + { + operationId = s_diagnosticListener.WriteConnectionCloseBefore(this); + // we want to cache the ClientConnectionId for After/Error logging, as when the connection + // is closed then we will lose this identifier + // + // note: caching this is only for diagnostics logging purposes + clientConnectionId = ClientConnectionId; + } + SqlStatistics statistics = null; TdsParser bestEffortCleanupTarget = null; + Exception e = null; RuntimeHelpers.PrepareConstrainedRegions(); try @@ -1348,20 +1374,28 @@ public override void Close() } catch (System.OutOfMemoryException ex) { + e = ex; Abort(ex); throw; } catch (System.StackOverflowException ex) { + e = ex; Abort(ex); throw; } catch (System.Threading.ThreadAbortException ex) { + e = ex; Abort(ex); SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } + catch (Exception ex) + { + e = ex; + throw; + } finally { SqlStatistics.StopTimer(statistics); @@ -1370,6 +1404,20 @@ public override void Close() { _lastIdentity.Dispose(); } + + // we only want to log this if the previous state of the + // connection is open, as that's the valid use-case + if (previousState != ConnectionState.Closed) + { + if (e != null) + { + s_diagnosticListener.WriteConnectionCloseError(operationId, clientConnectionId, this, e); + } + else + { + s_diagnosticListener.WriteConnectionCloseAfter(operationId, clientConnectionId, this); + } + } } } } @@ -1423,19 +1471,13 @@ public void Open(SqlConnectionOverrides overrides) { SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current); - if (StatisticsEnabled) - { - if (_statistics == null) - { - _statistics = new SqlStatistics(); - } - else - { - _statistics.ContinueOnNewConnection(); - } - } + Guid operationId = s_diagnosticListener.WriteConnectionOpenBefore(this); + + PrepareStatisticsForNewConnection(); SqlStatistics statistics = null; + Exception e = null; + RuntimeHelpers.PrepareConstrainedRegions(); try { @@ -1446,9 +1488,23 @@ public void Open(SqlConnectionOverrides overrides) throw ADP.InternalError(ADP.InternalErrorCode.SynchronousConnectReturnedPending); } } + catch (Exception ex) + { + e = ex; + throw; + } finally { SqlStatistics.StopTimer(statistics); + + if (e != null) + { + s_diagnosticListener.WriteConnectionOpenError(operationId, this, e); + } + else + { + s_diagnosticListener.WriteConnectionOpenAfter(operationId, this); + } } } } @@ -1696,17 +1752,9 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok try { - if (StatisticsEnabled) - { - if (_statistics == null) - { - _statistics = new SqlStatistics(); - } - else - { - _statistics.ContinueOnNewConnection(); - } - } + Guid operationId = s_diagnosticListener.WriteConnectionOpenBefore(this); + + PrepareStatisticsForNewConnection(); SqlStatistics statistics = null; RuntimeHelpers.PrepareConstrainedRegions(); @@ -1716,7 +1764,17 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok System.Transactions.Transaction transaction = ADP.GetCurrentTransaction(); TaskCompletionSource completion = new TaskCompletionSource(transaction); - TaskCompletionSource result = new TaskCompletionSource(); + TaskCompletionSource result = new TaskCompletionSource(state: this); + + if (s_diagnosticListener.IsEnabled(SqlClientConnectionOpenAfter.Name) || + s_diagnosticListener.IsEnabled(SqlClientConnectionOpenError.Name)) + { + result.Task.ContinueWith( + continuationAction: s_openAsyncComplete, + state: operationId, // connection is passed in TaskCompletionSource async state + scheduler: TaskScheduler.Default + ); + } if (cancellationToken.IsCancellationRequested) { @@ -1732,6 +1790,7 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok } catch (Exception e) { + s_diagnosticListener.WriteConnectionOpenError(operationId, this, e); result.SetException(e); return result.Task; } @@ -1755,6 +1814,11 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok return result.Task; } + catch (Exception ex) + { + s_diagnosticListener.WriteConnectionOpenError(operationId, this, ex); + throw; + } finally { SqlStatistics.StopTimer(statistics); @@ -1766,6 +1830,22 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok } } + private static void OpenAsyncComplete(Task task, object state) + { + Guid operationId = (Guid)state; + SqlConnection connection = (SqlConnection)task.AsyncState; + if (task.Exception != null) + { + SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlConnection.OpenAsyncComplete | Error | Correlation | Activity Id {0}, Exception {1}", ActivityCorrelator.Current, task.Exception.Message); + s_diagnosticListener.WriteConnectionOpenError(operationId, connection, task.Exception); + } + else + { + SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlConnection.OpenAsyncComplete | Info | Correlation | Activity Id {0}, Client Connection Id {1}", ActivityCorrelator.Current, connection?.ClientConnectionId); + s_diagnosticListener.WriteConnectionOpenAfter(operationId, connection); + } + } + private class OpenAsyncRetry { private SqlConnection _parent; @@ -1844,6 +1924,23 @@ internal void Retry(Task retryTask) } } + private void PrepareStatisticsForNewConnection() + { + if (StatisticsEnabled || + s_diagnosticListener.IsEnabled(SqlClientCommandAfter.Name) || + s_diagnosticListener.IsEnabled(SqlClientConnectionOpenAfter.Name)) + { + if (_statistics == null) + { + _statistics = new SqlStatistics(); + } + else + { + _statistics.ContinueOnNewConnection(); + } + } + } + private bool TryOpen(TaskCompletionSource retry, SqlConnectionOverrides overrides = SqlConnectionOverrides.None) { SqlConnectionString connectionOptions = (SqlConnectionString)ConnectionOptions; @@ -1929,7 +2026,10 @@ private bool TryOpenInner(TaskCompletionSource retry) GC.ReRegisterForFinalize(this); } - if (StatisticsEnabled) + // The _statistics can change with StatisticsEnabled. Copying to a local variable before checking for a null value. + SqlStatistics statistics = _statistics; + if (StatisticsEnabled || + (s_diagnosticListener.IsEnabled(SqlClientCommandAfter.Name) && statistics != null)) { _statistics._openTimestamp = ADP.TimerCurrent(); tdsInnerConnection.Parser.Statistics = _statistics; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticScope.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticScope.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticScope.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticScope.cs index 7033eee9d8..2ef13af2c3 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticScope.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticScope.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Runtime.CompilerServices; @@ -106,5 +104,3 @@ public void SetException(Exception ex) } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticTransactionScope.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticTransactionScope.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticTransactionScope.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticTransactionScope.cs index a0ffe49587..0dd73132e1 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticTransactionScope.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/DiagnosticTransactionScope.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Data; using System.Runtime.CompilerServices; @@ -157,5 +155,3 @@ public void SetException(Exception ex) } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandAfter.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandAfter.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandAfter.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandAfter.cs index 198b025779..992e2086d2 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandAfter.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandAfter.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -82,5 +80,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandBefore.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandBefore.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandBefore.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandBefore.cs index 3238a16eb8..71c9df6e1e 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandBefore.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandBefore.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -77,5 +75,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandError.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandError.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandError.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandError.cs index ea383305d0..b21d72b575 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandError.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientCommandError.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -82,5 +80,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseAfter.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseAfter.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseAfter.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseAfter.cs index c3905c2265..537a51212d 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseAfter.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseAfter.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -77,5 +75,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseBefore.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseBefore.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseBefore.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseBefore.cs index ab08c9d5c5..c891e8baaf 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseBefore.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseBefore.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -77,5 +75,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseError.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseError.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseError.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseError.cs index 8b9e51bacf..5c5f75b834 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseError.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionCloseError.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -84,5 +82,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenAfter.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenAfter.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenAfter.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenAfter.cs index b1deaec902..4d5d40025d 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenAfter.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenAfter.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -82,5 +80,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenBefore.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenBefore.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenBefore.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenBefore.cs index fff83cd3de..bf300a2180 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenBefore.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenBefore.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -72,5 +70,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenError.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenError.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenError.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenError.cs index 9823eac1d1..6d3b8d8943 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenError.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientConnectionOpenError.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -84,5 +82,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitAfter.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitAfter.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitAfter.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitAfter.cs index b4b44ae07c..66033ab85d 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitAfter.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitAfter.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -79,5 +77,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitBefore.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitBefore.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitBefore.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitBefore.cs index 8e9a6990eb..995b84f62b 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitBefore.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitBefore.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -78,5 +76,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitError.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitError.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitError.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitError.cs index be3e70b792..9321d84e26 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitError.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionCommitError.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -84,5 +82,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackAfter.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackAfter.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackAfter.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackAfter.cs index 99a31040f0..3166a561ba 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackAfter.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackAfter.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -83,5 +81,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackBefore.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackBefore.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackBefore.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackBefore.cs index f55f4fcd6d..3cd2c94d10 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackBefore.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackBefore.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -84,5 +82,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackError.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackError.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackError.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackError.cs index 9c2e16ba0b..4b32f29ca8 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackError.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlClientTransactionRollbackError.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Collections; using System.Collections.Generic; @@ -89,5 +87,3 @@ public IEnumerator> GetEnumerator() } } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs similarity index 96% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.netcore.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs index 2ce73d8988..ed8337eec7 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.netcore.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs @@ -2,14 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#if NET - using System; using System.Data; using System.Diagnostics; -using System.Reflection; using System.Runtime.CompilerServices; +#if NET +using System.Reflection; using System.Runtime.Loader; +#else +using System.Runtime.ConstrainedExecution; +#endif namespace Microsoft.Data.SqlClient.Diagnostics { @@ -17,7 +19,11 @@ internal sealed class SqlDiagnosticListener : DiagnosticListener { public SqlDiagnosticListener() : base("SqlClientDiagnosticListener") { - AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()).Unloading += SqlDiagnosticListener_Unloading; +#if NET + AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()).Unloading += SqlDiagnosticListener_UnloadingAssemblyLoadContext; +#else + AppDomain.CurrentDomain.DomainUnload += SqlDiagnosticListener_UnloadingAppDomain; +#endif } public DiagnosticScope CreateCommandScope( @@ -477,11 +483,13 @@ public void WriteTransactionRollbackError( ); } - private void SqlDiagnosticListener_Unloading(AssemblyLoadContext obj) - { +#if NET + private void SqlDiagnosticListener_UnloadingAssemblyLoadContext(AssemblyLoadContext obj) => Dispose(); - } +#else + [PrePrepareMethod] + private void SqlDiagnosticListener_UnloadingAppDomain(object sender, EventArgs e) => + Dispose(); +#endif } } - -#endif diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlTransaction.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlTransaction.cs index 8130b529d7..c8263aa888 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlTransaction.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlTransaction.cs @@ -9,10 +9,8 @@ using System.Diagnostics; using System.Threading; using Microsoft.Data.Common; - -#if NET using Microsoft.Data.SqlClient.Diagnostics; -#else +#if NETFRAMEWORK using System.Runtime.CompilerServices; #endif @@ -21,9 +19,7 @@ namespace Microsoft.Data.SqlClient /// public sealed class SqlTransaction : DbTransaction { - #if NET private static readonly SqlDiagnosticListener s_diagnosticListener = new(); - #endif private static int s_objectTypeCount; // EventSource Counter @@ -88,12 +84,10 @@ public override IsolationLevel IsolationLevel /// public override void Commit() { - #if NET using DiagnosticTransactionScope diagnosticScope = s_diagnosticListener.CreateTransactionCommitScope( _isolationLevel, _connection, InternalTransaction); - #endif ZombieCheck(); @@ -143,9 +137,7 @@ public override void Commit() #endif catch (SqlException ex) { - #if NET diagnosticScope.SetException(ex); - #endif // GitHub Issue #130 - When a timeout exception has occurred on transaction completion request, // this connection may not be in reusable state. @@ -156,13 +148,11 @@ public override void Commit() } throw; } - #if NET catch (Exception ex) { diagnosticScope.SetException(ex); throw; } - #endif finally { SqlStatistics.StopTimer(statistics); @@ -219,13 +209,11 @@ protected override void Dispose(bool disposing) /// public override void Rollback() { - #if NET using DiagnosticTransactionScope diagnosticScope = s_diagnosticListener.CreateTransactionRollbackScope( _isolationLevel, _connection, InternalTransaction, transactionName: null); - #endif if (Is2005PartialZombie) { @@ -281,13 +269,12 @@ public override void Rollback() SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } - #else + #endif catch (Exception ex) { diagnosticScope.SetException(ex); throw; } - #endif finally { SqlStatistics.StopTimer(statistics); @@ -304,13 +291,11 @@ public override void Rollback(string transactionName) public void Rollback(string transactionName) #endif { - #if NET using DiagnosticTransactionScope diagnosticScope = s_diagnosticListener.CreateTransactionRollbackScope( _isolationLevel, _connection, InternalTransaction, transactionName); - #endif #if NETFRAMEWORK SqlConnection.ExecutePermission.Demand(); // MDAC 81476 @@ -360,13 +345,12 @@ public void Rollback(string transactionName) SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } - #else + #endif catch (Exception ex) { diagnosticScope.SetException(ex); throw; } - #endif finally { SqlStatistics.StopTimer(statistics); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index 7bd503c5b9..6ab6a27688 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -253,8 +253,6 @@ - - @@ -339,6 +337,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + @@ -365,9 +364,6 @@ %(Filename)%(Extension) - - - PreserveNewest diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs index b8649d43d2..8ee8e28058 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs @@ -21,7 +21,6 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests { - [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] public class DiagnosticTest { private const string BadConnectionString = "data source = bad; initial catalog = bad; integrated security = true; connection timeout = 1;"; @@ -241,8 +240,13 @@ public void ExecuteScalarAsyncTest() { CollectStatisticsDiagnosticsAsync(async connectionString => { +#if NET await using (SqlConnection conn = new SqlConnection(connectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(connectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();"; @@ -262,8 +266,13 @@ public void ExecuteScalarAsyncErrorTest() { CollectStatisticsDiagnosticsAsync(async connectionString => { +#if NET await using (SqlConnection conn = new SqlConnection(connectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(connectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "SELECT 1 / 0;"; @@ -283,8 +292,13 @@ public void ExecuteNonQueryAsyncTest() { CollectStatisticsDiagnosticsAsync(async connectionString => { +#if NET await using (SqlConnection conn = new SqlConnection(connectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(connectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();"; @@ -304,8 +318,13 @@ public void ExecuteNonQueryAsyncErrorTest() { CollectStatisticsDiagnosticsAsync(async connectionString => { +#if NET await using (SqlConnection conn = new SqlConnection(connectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(connectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "SELECT 1 / 0;"; @@ -325,8 +344,13 @@ public void ExecuteReaderAsyncTest() { CollectStatisticsDiagnosticsAsync(async connectionString => { +#if NET await using (SqlConnection conn = new SqlConnection(connectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(connectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();"; @@ -350,8 +374,13 @@ public void ExecuteReaderAsyncErrorTest() { CollectStatisticsDiagnosticsAsync(async connectionString => { +#if NET await using (SqlConnection conn = new SqlConnection(connectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(connectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "SELECT 1 / 0;"; @@ -374,8 +403,13 @@ public void ExecuteXmlReaderAsyncTest() { CollectStatisticsDiagnosticsAsync(async _ => { +#if NET await using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "SELECT TOP 10 * FROM sys.objects FOR xml auto, xmldata;"; @@ -401,8 +435,13 @@ public void ExecuteXmlReaderAsyncErrorTest() CollectStatisticsDiagnosticsAsync(async _ => { +#if NET await using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) await using (SqlCommand cmd = new SqlCommand()) +#else + using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) + using (SqlCommand cmd = new SqlCommand()) +#endif { cmd.Connection = conn; cmd.CommandText = "select *, baddata = 1 / 0 from sys.objects for xml auto, xmldata;"; @@ -458,7 +497,11 @@ public void ConnectionOpenAsyncTest() { CollectStatisticsDiagnosticsAsync(async connectionString => { +#if NET await using (SqlConnection sqlConnection = new SqlConnection(connectionString)) +#else + using (SqlConnection sqlConnection = new SqlConnection(connectionString)) +#endif { await sqlConnection.OpenAsync(); } @@ -474,7 +517,11 @@ public void ConnectionOpenAsyncErrorTest() { CollectStatisticsDiagnosticsAsync(async _ => { +#if NET await using (SqlConnection sqlConnection = new SqlConnection(BadConnectionString)) +#else + using (SqlConnection sqlConnection = new SqlConnection(BadConnectionString)) +#endif { await Assert.ThrowsAsync(() => sqlConnection.OpenAsync()); } diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 0f029b4c19..4a602aceec 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -37,6 +37,7 @@ +