From 68e48d04d4593351a522f06bce0f828d02442168 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 21:18:18 +0100 Subject: [PATCH 01/10] Add explicit dependency for netfx: System.Diagnostics.DiagnosticSource --- src/Directory.Packages.props | 1 + .../netfx/ref/Microsoft.Data.SqlClient.csproj | 1 + .../netfx/src/Microsoft.Data.SqlClient.csproj | 1 + tools/specs/Microsoft.Data.SqlClient.nuspec | 1 + 4 files changed, 4 insertions(+) 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/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..6547864e94 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -961,6 +961,7 @@ + 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 @@ + From 65aa0ddca5ee1d281ad2fbf17a1799c1f19e021d Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 21:32:07 +0100 Subject: [PATCH 02/10] Rename diagnostic type files, include in netfx project --- .../src/Microsoft.Data.SqlClient.csproj | 72 +++++++++---------- .../netfx/src/Microsoft.Data.SqlClient.csproj | 54 ++++++++++++++ ...ticScope.netcore.cs => DiagnosticScope.cs} | 4 -- ...tcore.cs => DiagnosticTransactionScope.cs} | 4 -- ...er.netcore.cs => SqlClientCommandAfter.cs} | 4 -- ...e.netcore.cs => SqlClientCommandBefore.cs} | 4 -- ...or.netcore.cs => SqlClientCommandError.cs} | 4 -- ...re.cs => SqlClientConnectionCloseAfter.cs} | 4 -- ...e.cs => SqlClientConnectionCloseBefore.cs} | 4 -- ...re.cs => SqlClientConnectionCloseError.cs} | 4 -- ...ore.cs => SqlClientConnectionOpenAfter.cs} | 4 -- ...re.cs => SqlClientConnectionOpenBefore.cs} | 4 -- ...ore.cs => SqlClientConnectionOpenError.cs} | 4 -- ....cs => SqlClientTransactionCommitAfter.cs} | 4 -- ...cs => SqlClientTransactionCommitBefore.cs} | 4 -- ....cs => SqlClientTransactionCommitError.cs} | 4 -- ...s => SqlClientTransactionRollbackAfter.cs} | 4 -- ... => SqlClientTransactionRollbackBefore.cs} | 4 -- ...s => SqlClientTransactionRollbackError.cs} | 4 -- ...er.netcore.cs => SqlDiagnosticListener.cs} | 4 -- 20 files changed, 90 insertions(+), 108 deletions(-) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{DiagnosticScope.netcore.cs => DiagnosticScope.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{DiagnosticTransactionScope.netcore.cs => DiagnosticTransactionScope.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientCommandAfter.netcore.cs => SqlClientCommandAfter.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientCommandBefore.netcore.cs => SqlClientCommandBefore.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientCommandError.netcore.cs => SqlClientCommandError.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientConnectionCloseAfter.netcore.cs => SqlClientConnectionCloseAfter.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientConnectionCloseBefore.netcore.cs => SqlClientConnectionCloseBefore.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientConnectionCloseError.netcore.cs => SqlClientConnectionCloseError.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientConnectionOpenAfter.netcore.cs => SqlClientConnectionOpenAfter.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientConnectionOpenBefore.netcore.cs => SqlClientConnectionOpenBefore.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientConnectionOpenError.netcore.cs => SqlClientConnectionOpenError.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientTransactionCommitAfter.netcore.cs => SqlClientTransactionCommitAfter.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientTransactionCommitBefore.netcore.cs => SqlClientTransactionCommitBefore.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientTransactionCommitError.netcore.cs => SqlClientTransactionCommitError.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientTransactionRollbackAfter.netcore.cs => SqlClientTransactionRollbackAfter.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientTransactionRollbackBefore.netcore.cs => SqlClientTransactionRollbackBefore.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlClientTransactionRollbackError.netcore.cs => SqlClientTransactionRollbackError.cs} (99%) rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/{SqlDiagnosticListener.netcore.cs => SqlDiagnosticListener.cs} (99%) 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 36de19a385..8839e039af 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/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 6547864e94..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 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 99% 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..dcd25ce6a2 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,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.Diagnostics; @@ -483,5 +481,3 @@ private void SqlDiagnosticListener_Unloading(AssemblyLoadContext obj) } } } - -#endif From 5d436403f98121a355d68d506a1d36e143152af5 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 21:46:54 +0100 Subject: [PATCH 03/10] Enable AppDomain unload response in netfx --- .../Diagnostics/SqlDiagnosticListener.cs | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs index dcd25ce6a2..ed8337eec7 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs @@ -5,9 +5,13 @@ 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 { @@ -15,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( @@ -475,9 +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 } } From 232a09f50b5ae571ce601ebf590e49ab581efe90 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 21:50:25 +0100 Subject: [PATCH 04/10] Enable SqlTransaction telemetry --- .../Data/SqlClient/SqlTransaction.cs | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) 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); From 684c3e23c79a3fb38c95d76ab1ccdbb99fe269bc Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 22:08:32 +0100 Subject: [PATCH 05/10] Enable SqlConnection telemetry --- .../Microsoft/Data/SqlClient/SqlConnection.cs | 4 +- .../Microsoft/Data/SqlClient/SqlConnection.cs | 107 +++++++++++++++++- 2 files changed, 107 insertions(+), 4 deletions(-) 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 89535f5c06..caacb3a586 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 @@ -68,7 +68,7 @@ private enum CultureCheckState : uint 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 @@ -1457,8 +1457,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/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs index 6b4f9f81b9..3b32cef3f2 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. @@ -111,6 +115,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); /// @@ -1302,8 +1308,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 @@ -1336,20 +1362,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); @@ -1358,6 +1392,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); + } + } } } } @@ -1411,6 +1459,8 @@ public void Open(SqlConnectionOverrides overrides) { SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current); + Guid operationId = s_diagnosticListener.WriteConnectionOpenBefore(this); + if (StatisticsEnabled) { if (_statistics == null) @@ -1424,6 +1474,8 @@ public void Open(SqlConnectionOverrides overrides) } SqlStatistics statistics = null; + Exception e = null; + RuntimeHelpers.PrepareConstrainedRegions(); try { @@ -1434,9 +1486,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); + } } } } @@ -1684,6 +1750,8 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok try { + Guid operationId = s_diagnosticListener.WriteConnectionOpenBefore(this); + if (StatisticsEnabled) { if (_statistics == null) @@ -1704,7 +1772,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) { @@ -1720,6 +1798,7 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok } catch (Exception e) { + s_diagnosticListener.WriteConnectionOpenError(operationId, this, e); result.SetException(e); return result.Task; } @@ -1743,6 +1822,11 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok return result.Task; } + catch (Exception ex) + { + s_diagnosticListener.WriteConnectionOpenError(operationId, this, ex); + throw; + } finally { SqlStatistics.StopTimer(statistics); @@ -1754,6 +1838,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; @@ -1917,7 +2017,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; From 7c093fa6461a2ed96ad2fbdc94686025a756eb6c Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 22:48:51 +0100 Subject: [PATCH 06/10] Add telemetry classes to netfx ref assembly --- .../netfx/ref/Microsoft.Data.SqlClient.cs | 411 ++++++++++++++++++ 1 file changed, 411 insertions(+) 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 { /// From e458c2465d6e7a34f48d4b3f9c951f38bd1239d8 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 23:14:48 +0100 Subject: [PATCH 07/10] Initial enablement of diagnostics tests on netfx --- ....Data.SqlClient.ManualTesting.Tests.csproj | 6 +-- .../TracingTests/DiagnosticTest.cs | 49 ++++++++++++++++++- 2 files changed, 49 insertions(+), 6 deletions(-) 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 98f790aac1..f8cd5e9c9c 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 @@ -254,8 +254,6 @@ - - @@ -340,6 +338,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + @@ -366,9 +365,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()); } From bc9980a1bc1776681e6dea452699cf9c91febabc Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat, 19 Jul 2025 23:30:16 +0100 Subject: [PATCH 08/10] Port PrepareStatisticsForNewConnection to netfx --- .../Microsoft/Data/SqlClient/SqlConnection.cs | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) 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 3b32cef3f2..3cb40be3c0 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 @@ -1461,17 +1461,7 @@ public void Open(SqlConnectionOverrides overrides) Guid operationId = s_diagnosticListener.WriteConnectionOpenBefore(this); - if (StatisticsEnabled) - { - if (_statistics == null) - { - _statistics = new SqlStatistics(); - } - else - { - _statistics.ContinueOnNewConnection(); - } - } + PrepareStatisticsForNewConnection(); SqlStatistics statistics = null; Exception e = null; @@ -1752,17 +1742,7 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok { Guid operationId = s_diagnosticListener.WriteConnectionOpenBefore(this); - if (StatisticsEnabled) - { - if (_statistics == null) - { - _statistics = new SqlStatistics(); - } - else - { - _statistics.ContinueOnNewConnection(); - } - } + PrepareStatisticsForNewConnection(); SqlStatistics statistics = null; RuntimeHelpers.PrepareConstrainedRegions(); @@ -1932,6 +1912,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; From d14a56134fd4fe5512a5cf0060e9afb0d9927f2e Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Thu, 24 Jul 2025 20:43:07 +0100 Subject: [PATCH 09/10] Enable SqlCommand telemetry --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 2 +- .../Microsoft/Data/SqlClient/SqlCommand.cs | 103 +++++++++++++++--- 2 files changed, 86 insertions(+), 19 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 f4f38dbe73..bbb56e8757 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 @@ -1233,7 +1233,7 @@ public override int ExecuteNonQuery() // between entry into Execute* API and the thread obtaining the stateObject. _pendingCancel = false; - using (var diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) + using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create("SqlCommand.ExecuteNonQuery | API | Object Id {0}", ObjectID)) { SqlStatistics statistics = null; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index d65a0b7522..a0759d914b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -21,6 +21,7 @@ using System.Buffers; using Microsoft.Data.Common; using Microsoft.Data.Sql; +using Microsoft.Data.SqlClient.Diagnostics; using Microsoft.Data.SqlClient.Server; using System.Transactions; using System.Collections.Concurrent; @@ -162,6 +163,10 @@ protected override void AfterCleared(SqlCommand owner) /// private static bool _forceRetryableEnclaveQueryExecutionExceptionDuringGenerateEnclavePackage = false; #endif + + private static readonly SqlDiagnosticListener s_diagnosticListener = new SqlDiagnosticListener(); + private bool _parentOperationStarted = false; + internal static readonly Action s_cancelIgnoreFailure = CancelIgnoreFailureCallback; // Prepare @@ -632,7 +637,8 @@ internal SqlStatistics Statistics { if (_activeConnection != null) { - if (_activeConnection.StatisticsEnabled) + if (_activeConnection.StatisticsEnabled || + s_diagnosticListener.IsEnabled(SqlClientCommandAfter.Name)) { return _activeConnection.Statistics; } @@ -1228,6 +1234,7 @@ public override object ExecuteScalar() _pendingCancel = false; SqlStatistics statistics = null; + using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create("SqlCommand.ExecuteScalar | API | ObjectId {0}", ObjectID)) { bool success = false; @@ -1245,9 +1252,13 @@ public override object ExecuteScalar() success = true; return result; } - catch (SqlException ex) + catch (Exception ex) { - sqlExceptionNumber = ex.Number; + diagnosticScope.SetException(ex); + if (ex is SqlException sqlException) + { + sqlExceptionNumber = sqlException.Number; + } throw; } finally @@ -1318,6 +1329,7 @@ public override int ExecuteNonQuery() SqlStatistics statistics = null; + using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create(" {0}", ObjectID)) { bool success = false; @@ -1344,9 +1356,13 @@ public override int ExecuteNonQuery() success = true; return _rowsAffected; } - catch (SqlException ex) + catch (Exception ex) { - sqlExceptionNumber = ex.Number; + diagnosticScope.SetException(ex); + if (ex is SqlException sqlException) + { + sqlExceptionNumber = sqlException.Number; + } throw; } finally @@ -1916,6 +1932,7 @@ public XmlReader ExecuteXmlReader() SqlStatistics statistics = null; + using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create("SqlCommand.ExecuteXmlReader | API | Object Id {0}", ObjectID)) { bool success = false; @@ -1935,9 +1952,13 @@ public XmlReader ExecuteXmlReader() success = true; return result; } - catch (SqlException ex) + catch (Exception ex) { - sqlExceptionNumber = ex.Number; + diagnosticScope.SetException(ex); + if (ex is SqlException sqlException) + { + sqlExceptionNumber = sqlException.Number; + } throw; } finally @@ -2293,6 +2314,8 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) RuntimeHelpers.PrepareConstrainedRegions(); bool success = false; int? sqlExceptionNumber = null; + Exception e = null; + Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); using (TryEventScope.Create("SqlCommand.ExecuteReader | API | Object Id {0}", ObjectID)) { @@ -2307,31 +2330,44 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) success = true; return result; } - catch (SqlException e) + catch (System.OutOfMemoryException ex) { - sqlExceptionNumber = e.Number; + _activeConnection.Abort(ex); throw; } - catch (System.OutOfMemoryException e) + catch (System.StackOverflowException ex) { - _activeConnection.Abort(e); + _activeConnection.Abort(ex); throw; } - catch (System.StackOverflowException e) + catch (System.Threading.ThreadAbortException ex) { - _activeConnection.Abort(e); + _activeConnection.Abort(ex); + SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } - catch (System.Threading.ThreadAbortException e) + catch (Exception ex) { - _activeConnection.Abort(e); - SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); + if (ex is SqlException sqlException) + { + sqlExceptionNumber = sqlException.Number; + } + + e = ex; throw; } finally { SqlStatistics.StopTimer(statistics); WriteEndExecuteEvent(success, sqlExceptionNumber, synchronous: true); + if (e != null) + { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); + } + else + { + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); + } } } } @@ -2433,10 +2469,18 @@ private void CleanupExecuteReaderAsync(Task task, TaskCompletionS if (task.IsFaulted) { Exception e = task.Exception.InnerException; + if (!_parentOperationStarted) + { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); + } source.SetException(e); } else { + if (!_parentOperationStarted) + { + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); + } if (task.IsCanceled) { source.SetCanceled(); @@ -2832,7 +2876,7 @@ private Task InternalExecuteNonQueryAsync(CancellationToken cancellationTok { SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.InternalExecuteNonQueryAsync | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText); SqlConnection.ExecutePermission.Demand(); - Guid operationId = Guid.Empty; + Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); // connection can be used as state in RegisterForConnectionCloseNotification continuation // to avoid an allocation so use it as the state value if possible but it can be changed if @@ -2885,6 +2929,7 @@ private Task InternalExecuteNonQueryAsync(CancellationToken cancellationTok } catch (Exception e) { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); context.Dispose(); } @@ -2897,6 +2942,7 @@ private void CleanupAfterExecuteNonQueryAsync(Task task, TaskCompletionSour if (task.IsFaulted) { Exception e = task.Exception.InnerException; + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); } else @@ -2909,6 +2955,7 @@ private void CleanupAfterExecuteNonQueryAsync(Task task, TaskCompletionSour { source.SetResult(task.Result); } + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); } } @@ -2960,6 +3007,10 @@ private Task InternalExecuteReaderAsync(CommandBehavior behavior, SqlClientEventSource.Log.TryTraceEvent("SqlCommand.InternalExecuteReaderAsync | API> {0}, Client Connection Id {1}, Command Text = '{2}'", ObjectID, Connection?.ClientConnectionId, CommandText); SqlConnection.ExecutePermission.Demand(); Guid operationId = default(Guid); + if (!_parentOperationStarted) + { + operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); + } // connection can be used as state in RegisterForConnectionCloseNotification continuation // to avoid an allocation so use it as the state value if possible but it can be changed if @@ -3021,6 +3072,11 @@ private Task InternalExecuteReaderAsync(CommandBehavior behavior, } catch (Exception e) { + if (!_parentOperationStarted) + { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); + } + source.SetException(e); context?.Dispose(); } @@ -3059,6 +3115,9 @@ public override Task ExecuteScalarAsync(CancellationToken cancellationTo private Task InternalExecuteScalarAsync(CancellationToken cancellationToken) { + _parentOperationStarted = true; + Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); + return ExecuteReaderAsync(cancellationToken).ContinueWith((executeTask) => { TaskCompletionSource source = new TaskCompletionSource(); @@ -3068,6 +3127,7 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo } else if (executeTask.IsFaulted) { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, executeTask.Exception.InnerException); source.SetException(executeTask.Exception.InnerException); } else @@ -3086,6 +3146,7 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo else if (readTask.IsFaulted) { reader.Dispose(); + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, readTask.Exception.InnerException); source.SetException(readTask.Exception.InnerException); } else @@ -3113,10 +3174,12 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo } if (exception != null) { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, exception); source.SetException(exception); } else { + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); source.SetResult(result); } } @@ -3130,6 +3193,7 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo TaskScheduler.Default ); } + _parentOperationStarted = false; return source.Task; }, TaskScheduler.Default).Unwrap(); } @@ -3154,7 +3218,7 @@ private Task InternalExecuteXmlReaderAsync(CancellationToken cancella { SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.InternalExecuteXmlReaderAsync | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText); SqlConnection.ExecutePermission.Demand(); - Guid operationId = Guid.Empty; + Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); // connection can be used as state in RegisterForConnectionCloseNotification continuation // to avoid an allocation so use it as the state value if possible but it can be changed if @@ -3214,6 +3278,7 @@ private Task InternalExecuteXmlReaderAsync(CancellationToken cancella } catch (Exception e) { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); } @@ -3225,6 +3290,7 @@ private void CleanupAfterExecuteXmlReaderAsync(Task task, TaskComplet if (task.IsFaulted) { Exception e = task.Exception.InnerException; + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); } else @@ -3237,6 +3303,7 @@ private void CleanupAfterExecuteXmlReaderAsync(Task task, TaskComplet { source.SetResult(task.Result); } + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); } } From d41b6ed790ff8080061951e7885f89150cc01ccc Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Thu, 24 Jul 2025 20:48:40 +0100 Subject: [PATCH 10/10] Revert "Enable SqlCommand telemetry" This reverts commit d14a56134fd4fe5512a5cf0060e9afb0d9927f2e. Enables ongoing merge work on SqlCommand to continue. --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 2 +- .../Microsoft/Data/SqlClient/SqlCommand.cs | 103 +++--------------- 2 files changed, 19 insertions(+), 86 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 bbb56e8757..f4f38dbe73 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 @@ -1233,7 +1233,7 @@ public override int ExecuteNonQuery() // between entry into Execute* API and the thread obtaining the stateObject. _pendingCancel = false; - using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) + using (var diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create("SqlCommand.ExecuteNonQuery | API | Object Id {0}", ObjectID)) { SqlStatistics statistics = null; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index a0759d914b..d65a0b7522 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -21,7 +21,6 @@ using System.Buffers; using Microsoft.Data.Common; using Microsoft.Data.Sql; -using Microsoft.Data.SqlClient.Diagnostics; using Microsoft.Data.SqlClient.Server; using System.Transactions; using System.Collections.Concurrent; @@ -163,10 +162,6 @@ protected override void AfterCleared(SqlCommand owner) /// private static bool _forceRetryableEnclaveQueryExecutionExceptionDuringGenerateEnclavePackage = false; #endif - - private static readonly SqlDiagnosticListener s_diagnosticListener = new SqlDiagnosticListener(); - private bool _parentOperationStarted = false; - internal static readonly Action s_cancelIgnoreFailure = CancelIgnoreFailureCallback; // Prepare @@ -637,8 +632,7 @@ internal SqlStatistics Statistics { if (_activeConnection != null) { - if (_activeConnection.StatisticsEnabled || - s_diagnosticListener.IsEnabled(SqlClientCommandAfter.Name)) + if (_activeConnection.StatisticsEnabled) { return _activeConnection.Statistics; } @@ -1234,7 +1228,6 @@ public override object ExecuteScalar() _pendingCancel = false; SqlStatistics statistics = null; - using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create("SqlCommand.ExecuteScalar | API | ObjectId {0}", ObjectID)) { bool success = false; @@ -1252,13 +1245,9 @@ public override object ExecuteScalar() success = true; return result; } - catch (Exception ex) + catch (SqlException ex) { - diagnosticScope.SetException(ex); - if (ex is SqlException sqlException) - { - sqlExceptionNumber = sqlException.Number; - } + sqlExceptionNumber = ex.Number; throw; } finally @@ -1329,7 +1318,6 @@ public override int ExecuteNonQuery() SqlStatistics statistics = null; - using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create(" {0}", ObjectID)) { bool success = false; @@ -1356,13 +1344,9 @@ public override int ExecuteNonQuery() success = true; return _rowsAffected; } - catch (Exception ex) + catch (SqlException ex) { - diagnosticScope.SetException(ex); - if (ex is SqlException sqlException) - { - sqlExceptionNumber = sqlException.Number; - } + sqlExceptionNumber = ex.Number; throw; } finally @@ -1932,7 +1916,6 @@ public XmlReader ExecuteXmlReader() SqlStatistics statistics = null; - using (DiagnosticScope diagnosticScope = s_diagnosticListener.CreateCommandScope(this, _transaction)) using (TryEventScope.Create("SqlCommand.ExecuteXmlReader | API | Object Id {0}", ObjectID)) { bool success = false; @@ -1952,13 +1935,9 @@ public XmlReader ExecuteXmlReader() success = true; return result; } - catch (Exception ex) + catch (SqlException ex) { - diagnosticScope.SetException(ex); - if (ex is SqlException sqlException) - { - sqlExceptionNumber = sqlException.Number; - } + sqlExceptionNumber = ex.Number; throw; } finally @@ -2314,8 +2293,6 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) RuntimeHelpers.PrepareConstrainedRegions(); bool success = false; int? sqlExceptionNumber = null; - Exception e = null; - Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); using (TryEventScope.Create("SqlCommand.ExecuteReader | API | Object Id {0}", ObjectID)) { @@ -2330,44 +2307,31 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) success = true; return result; } - catch (System.OutOfMemoryException ex) + catch (SqlException e) { - _activeConnection.Abort(ex); + sqlExceptionNumber = e.Number; throw; } - catch (System.StackOverflowException ex) + catch (System.OutOfMemoryException e) { - _activeConnection.Abort(ex); + _activeConnection.Abort(e); throw; } - catch (System.Threading.ThreadAbortException ex) + catch (System.StackOverflowException e) { - _activeConnection.Abort(ex); - SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); + _activeConnection.Abort(e); throw; } - catch (Exception ex) + catch (System.Threading.ThreadAbortException e) { - if (ex is SqlException sqlException) - { - sqlExceptionNumber = sqlException.Number; - } - - e = ex; + _activeConnection.Abort(e); + SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } finally { SqlStatistics.StopTimer(statistics); WriteEndExecuteEvent(success, sqlExceptionNumber, synchronous: true); - if (e != null) - { - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); - } - else - { - s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); - } } } } @@ -2469,18 +2433,10 @@ private void CleanupExecuteReaderAsync(Task task, TaskCompletionS if (task.IsFaulted) { Exception e = task.Exception.InnerException; - if (!_parentOperationStarted) - { - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); - } source.SetException(e); } else { - if (!_parentOperationStarted) - { - s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); - } if (task.IsCanceled) { source.SetCanceled(); @@ -2876,7 +2832,7 @@ private Task InternalExecuteNonQueryAsync(CancellationToken cancellationTok { SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.InternalExecuteNonQueryAsync | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText); SqlConnection.ExecutePermission.Demand(); - Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); + Guid operationId = Guid.Empty; // connection can be used as state in RegisterForConnectionCloseNotification continuation // to avoid an allocation so use it as the state value if possible but it can be changed if @@ -2929,7 +2885,6 @@ private Task InternalExecuteNonQueryAsync(CancellationToken cancellationTok } catch (Exception e) { - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); context.Dispose(); } @@ -2942,7 +2897,6 @@ private void CleanupAfterExecuteNonQueryAsync(Task task, TaskCompletionSour if (task.IsFaulted) { Exception e = task.Exception.InnerException; - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); } else @@ -2955,7 +2909,6 @@ private void CleanupAfterExecuteNonQueryAsync(Task task, TaskCompletionSour { source.SetResult(task.Result); } - s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); } } @@ -3007,10 +2960,6 @@ private Task InternalExecuteReaderAsync(CommandBehavior behavior, SqlClientEventSource.Log.TryTraceEvent("SqlCommand.InternalExecuteReaderAsync | API> {0}, Client Connection Id {1}, Command Text = '{2}'", ObjectID, Connection?.ClientConnectionId, CommandText); SqlConnection.ExecutePermission.Demand(); Guid operationId = default(Guid); - if (!_parentOperationStarted) - { - operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); - } // connection can be used as state in RegisterForConnectionCloseNotification continuation // to avoid an allocation so use it as the state value if possible but it can be changed if @@ -3072,11 +3021,6 @@ private Task InternalExecuteReaderAsync(CommandBehavior behavior, } catch (Exception e) { - if (!_parentOperationStarted) - { - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); - } - source.SetException(e); context?.Dispose(); } @@ -3115,9 +3059,6 @@ public override Task ExecuteScalarAsync(CancellationToken cancellationTo private Task InternalExecuteScalarAsync(CancellationToken cancellationToken) { - _parentOperationStarted = true; - Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); - return ExecuteReaderAsync(cancellationToken).ContinueWith((executeTask) => { TaskCompletionSource source = new TaskCompletionSource(); @@ -3127,7 +3068,6 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo } else if (executeTask.IsFaulted) { - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, executeTask.Exception.InnerException); source.SetException(executeTask.Exception.InnerException); } else @@ -3146,7 +3086,6 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo else if (readTask.IsFaulted) { reader.Dispose(); - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, readTask.Exception.InnerException); source.SetException(readTask.Exception.InnerException); } else @@ -3174,12 +3113,10 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo } if (exception != null) { - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, exception); source.SetException(exception); } else { - s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); source.SetResult(result); } } @@ -3193,7 +3130,6 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo TaskScheduler.Default ); } - _parentOperationStarted = false; return source.Task; }, TaskScheduler.Default).Unwrap(); } @@ -3218,7 +3154,7 @@ private Task InternalExecuteXmlReaderAsync(CancellationToken cancella { SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlCommand.InternalExecuteXmlReaderAsync | API | Correlation | Object Id {0}, Activity Id {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText); SqlConnection.ExecutePermission.Demand(); - Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); + Guid operationId = Guid.Empty; // connection can be used as state in RegisterForConnectionCloseNotification continuation // to avoid an allocation so use it as the state value if possible but it can be changed if @@ -3278,7 +3214,6 @@ private Task InternalExecuteXmlReaderAsync(CancellationToken cancella } catch (Exception e) { - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); } @@ -3290,7 +3225,6 @@ private void CleanupAfterExecuteXmlReaderAsync(Task task, TaskComplet if (task.IsFaulted) { Exception e = task.Exception.InnerException; - s_diagnosticListener.WriteCommandError(operationId, this, _transaction, e); source.SetException(e); } else @@ -3303,7 +3237,6 @@ private void CleanupAfterExecuteXmlReaderAsync(Task task, TaskComplet { source.SetResult(task.Result); } - s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); } }