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
-
-
@@ -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);
}
}