Skip to content

Reduce automated test crashes - #2968

Merged
paulmedynski merged 8 commits into
dotnet:mainfrom
edwardneal:stabilise-test-threading
Jul 9, 2025
Merged

paulmedynski merged 8 commits into
dotnet:mainfrom
edwardneal:stabilise-test-threading

Conversation

@edwardneal

@edwardneal edwardneal commented Nov 3, 2024 •

Copy link
Copy Markdown
Contributor

This is an attempt to stabilise the automated tests slightly. They sometimes crash and need to be restarted; I've recently been able to reproduce the same behaviour in my local testing.

Several tests instantiate a number of threads, and these threads don't handle exceptions (such as failed test assertions.) If these assertions fail, the testhost exits.

I've converted these threads to tasks, specifying TaskCreationOptions.LongRunning. This will force the task scheduler to give the task its own thread, and it'll mean that the exceptions are propagated back to the caller. The test will thus fail, but the testhost will stay running.

This should hopefully mean that ManualTests consistently takes about 15-20 minutes to run, rather than occasionally taking 30-40 minutes.

The key advantage is that exceptions propagate properly.
If a thread throws an exception (as a result of a failed test assertion, or otherwise) then the test host crashes and must be restarted.
…tion behaviour testing.

This should also allow the test to run on both netcore and netfx.
@edwardneal

edwardneal commented Nov 3, 2024 •

Copy link
Copy Markdown
Contributor Author

While not strictly related to this, two comments on the ApiShould.TestSqlCommandCancel test: this is always going to be a somewhat flaky test.

The flaky part of the test methodology is as follows:

  • Create a SqlCommand
  • Start Thread A, which calls SqlCommand.ExecuteNonQuery/.ExecuteReader on it. Expect it to return an exception indicating that it's been cancelled
  • Start Thread B, which calls SqlCommand.Cancel

Besides using threads directly, the current code enables Thread A to run immediately, while Thread B sleeps for 0.5s. This introduces a race condition where sometimes the command could have finished executing before the cancellation runs. In such a case, the original Assert.Throws call would fail (because ExecuteNonQuery/ExecuteReader completes without throwing an InvalidOperationException.) There was also an edge case where ExecuteNonQuery/ExecuteReader might throw a SqlException rather than an InvalidOperationException. In both of these cases, the exceptions went unhandled, the thread crashed and the testhost restarted.

I've tried to rework this coordination slightly with an interlock and a tweak to the approach:

  1. Thread A now waits for a ManualResetEvent controlled by Thread B. Thread B will only set this MRE directly before calling SqlCommand.Cancel
  2. Thread B now hammers calls to SqlCommand.Cancel until it receives a signal on an MRE controlled by Thread A. Thread A sets this signal when the ExecuteNonQuery/ExecuteReader call has finished

This reduces the race condition, but doesn't eliminate it: calling ExecuteNonQuery and ExecuteReader implicitly resets the SqlCommand's cancellation status, so it's possible that thread B might call Cancel, then thread A might reset this. We can never guarantee that a single Cancel call (or X sequential Cancel calls) will be enough to actually cancel the command; this is why Thread B now calls Cancel in a loop.

A second comment on the same TestSqlCommandCancel test: following my changes, there's another couple of errors which look worrying:

Managed SNI, on Linux
  [xUnit.net 00:01:29.38]     Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(connection: "Data Source=tcp:10.0.0.4;Database=NORTHWIND;UID=sa"···, value: "ExecuteNonQuery") [FAIL]
  [xUnit.net 00:01:29.39]       System.AggregateException : One or more errors occurred. (Assert.Equal() Failure: Strings differ
  [xUnit.net 00:01:29.39]                  ↓ (pos 0)
  [xUnit.net 00:01:29.39]       Expected: "Operation cancelled by user."
  [xUnit.net 00:01:29.39]       Actual:   "The request failed to run because the bat"···
  [xUnit.net 00:01:29.39]                  ↑ (pos 0))
  [xUnit.net 00:01:29.39]       ---- Assert.Equal() Failure: Strings differ
  [xUnit.net 00:01:29.39]                  ↓ (pos 0)
  [xUnit.net 00:01:29.39]       Expected: "Operation cancelled by user."
  [xUnit.net 00:01:29.39]       Actual:   "The request failed to run because the bat"···
  [xUnit.net 00:01:29.39]                  ↑ (pos 0)
  [xUnit.net 00:01:29.39]       Stack Trace:
  [xUnit.net 00:01:29.39]            at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
  [xUnit.net 00:01:29.39]            at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
  [xUnit.net 00:01:29.39]            at System.Threading.Tasks.Task.Wait()
  [xUnit.net 00:01:29.39]         /_/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs(2012,0): at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(String connection, String value)
  [xUnit.net 00:01:29.39]            at InvokeStub_ApiShould.TestSqlCommandCancel(Object, Span`1)
  [xUnit.net 00:01:29.39]            at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
  [xUnit.net 00:01:29.39]         ----- Inner Stack Trace -----
  [xUnit.net 00:01:29.39]         /_/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs(3160,0): at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.Thread_ExecuteNonQuery(Object state)
  [xUnit.net 00:01:29.39]            at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
  [xUnit.net 00:01:29.39]         --- End of stack trace from previous location ---
  [xUnit.net 00:01:29.39]            at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
  [xUnit.net 00:01:29.39]            at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
Native SNI, on Windows
  [xUnit.net 00:01:29.12]     Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(connection: "Data Source=tcp:10.0.0.4;Database=NORTHWIND;UID=sa"..., value: "ExecuteReader") [FAIL]
  [xUnit.net 00:01:29.12]       System.AggregateException : One or more errors occurred.
  [xUnit.net 00:01:29.12]       ---- Assert.Equal() Failure
  [xUnit.net 00:01:29.12]                 Γåô (pos 0)
  [xUnit.net 00:01:29.12]       Expected: Operation cancelled by user.
  [xUnit.net 00:01:29.12]       Actual:   A severe error occurred on the current co┬╖┬╖┬╖
  [xUnit.net 00:01:29.12]                 Γåæ (pos 0)
  [xUnit.net 00:01:29.13]       Stack Trace:
  [xUnit.net 00:01:29.13]            at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
  [xUnit.net 00:01:29.13]            at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
  [xUnit.net 00:01:29.13]            at System.Threading.Tasks.Task.Wait()
  [xUnit.net 00:01:29.13]         /_/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs(2013,0): at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(String connection, String value)
  [xUnit.net 00:01:29.13]         ----- Inner Stack Trace -----
  [xUnit.net 00:01:29.13]         /_/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs(3138,0): at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.Thread_ExecuteReader(Object state)
  [xUnit.net 00:01:29.13]            at System.Threading.Tasks.Task.Execute()

I think the managed SNI exception message is probably "The request failed to run because the batch is aborted, this can be caused by abort signal sent from client, or another request is running in the same session, which makes the session busy." If so, it's another instance of #26. The native SNI exception message looks like a bug though.


While this test can fail in two ways, the failure now shows up as a test failure rather than a crash & restart of testhost. I can revert my third commit (the changes to TestSqlCommandCancel) if it's better discussed in an issue.

@benrr101 benrr101 added the Area\Tests Issues that are targeted to tests or test projects label Nov 5, 2024

@benrr101 benrr101 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@edwardneal thanks so much for helping to make our automated testing more robust!! This is one of my biggest complaints in my day to day work, so anything that reduces the number of times I have to restart a build b/c of flaky tests is super appreciated.

I do have some concerns regarding the interlocking change, and a few other comments I'd like to see addressed before checking it in. But, I'll approve it asap once they are addressed

Comment thread src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs Outdated
* Removed two unnecessary iterations from DatabaseHelper.
* Added explanatory comments to ApiShould.
* Switched to using Task.WaitAll rather than waiting for each Task in sequence.
benrr101
benrr101 previously approved these changes Nov 14, 2024
@benrr101

Copy link
Copy Markdown
Contributor

@edwardneal Thanks again for working on this. I really really appreciate any help with improving our build process.

Once we get another review, I'll be happy to merge this 👍🚀

@benrr101 benrr101 added this to the 6.0-preview3 milestone Nov 14, 2024
cheenamalhotra
cheenamalhotra previously approved these changes Nov 15, 2024
@cheenamalhotra

Copy link
Copy Markdown
Member

It seems there are test failures:

Failed Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(connection: "Data Source=tcp:10.0.0.5;Database=NORTHWIND;UID=sa"···, value: "ExecuteNonQuery") [1 s]
EXEC : error Message:  [/mnt/vss/_work/1/s/build.proj]
     System.AggregateException : One or more errors occurred. (Assert.Equal() Failure: Strings differ
             ↓ (pos 0)
  Expected: "Operation cancelled by user."
  Actual:   "The request failed to run because the bat"···
             ↑ (pos 0))
  ---- Assert.Equal() Failure: Strings differ
             ↓ (pos 0)
  Expected: "Operation cancelled by user."
  Actual:   "The request failed to run because the bat"···
             ↑ (pos 0)
    Stack Trace:
       at System.Threading.Tasks.Task.WaitAllCore(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
     at System.Threading.Tasks.Task.WaitAll(Task[] tasks)
     at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(String connection, String value) in /_/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs:line 2134
     at InvokeStub_ApiShould.TestSqlCommandCancel(Object, Span`1)
     at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
...

Failed Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(connection: "Data Source=tcp:10.0.0.4;Database=NORTHWIND;UID=sa"···, value: "ExecuteReader") [1 s]
EXEC : error Message:  [/mnt/vss/_work/1/s/build.proj]
     System.AggregateException : One or more errors occurred. (Assert.Equal() Failure: Strings differ
             ↓ (pos 0)
  Expected: "Operation cancelled by user."
  Actual:   "The request failed to run because the bat"···
             ↑ (pos 0))
  ---- Assert.Equal() Failure: Strings differ
             ↓ (pos 0)
  Expected: "Operation cancelled by user."
  Actual:   "The request failed to run because the bat"···
             ↑ (pos 0)
    Stack Trace:
       at System.Threading.Tasks.Task.WaitAllCore(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
     at System.Threading.Tasks.Task.WaitAll(Task[] tasks)
     at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(String connection, String value) in /_/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs:line 2080
     at InvokeStub_ApiShould.TestSqlCommandCancel(Object, Span`1)
     at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
...

@cheenamalhotra

Copy link
Copy Markdown
Member

It also appears this test failed on Windows too in first round and passed on rerunning, so I'm a little skeptic of this change, though they look promising..

Failed Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(connection: "Data Source=tcp:10.0.0.4;Database=NORTHWIND;UID=sa"..., value: "ExecuteReader") [976 ms]
##[error]EXEC(0,0): Error Message: 
EXEC : error Message:  [D:\a\_work\1\s\build.proj]
     System.AggregateException : One or more errors occurred.
  ---- Assert.Equal() Failure
            Γåô (pos 0)
  Expected: Operation cancelled by user.
  Actual:   A severe error occurred on the current co┬╖┬╖┬╖
            Γåæ (pos 0)
    Stack Trace:
       at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
     at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout)
     at System.Threading.Tasks.Task.WaitAll(Task[] tasks)
     at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(String connection, String value) in /_/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs:line 2027

@edwardneal

edwardneal commented Nov 15, 2024 •

Copy link
Copy Markdown
Contributor Author

Thanks @cheenamalhotra, that's fair. The main objective of this PR is to prevent the exceptions thrown by the secondary thread from killing the testhost process. At the moment, a flaky test kills the process and CI restarts it; this adds 10-15 minutes to the build time. With this change, the flaky test fails, the process returns a non-zero exit code and CI restarts it.

I hadn't spotted the second restart criteria earlier, so this PR doesn't reduce the build time as I first thought. It does make some previously-failing tests visible though, and hopefully some future work can start moving progressively more tests into a test run which doesn't have that restart criteria, allowing us to shift the remaining ones towards restarting the individual test rather than the entire testhost.

The exception message which starts with "The request failed to run because the bat" is a simple enough fix, I'm pretty sure it's just another instance of efcore#29861 and will change the test to account for that. I'm more concerned about the exception with the corrupted message string though. That looks a little like the native SNI's SNIGetLastError method is overwriting or freeing the memory behind the SNI_Error.errorMessage member which it returns to TdsParser.

Edit: looks like there are a few additional possible exception messages which can report cancellation. That's a little frustrating - I'd hoped running it until it failed in VS would catch them all. I'll keep looking...

Cancellation can trigger one of several different errors, resulting in a flakier test.
Also ensure that the query always takes more than 150ms, ensuring that a quick query execution doesn't cause the test to fail.
Finally, make sure that we try to read everything from the SqlDataReader.
@cheenamalhotra
cheenamalhotra self-requested a review November 15, 2024 22:11
@cheenamalhotra cheenamalhotra removed this from the 6.0-preview3 milestone Nov 15, 2024
@cheenamalhotra
cheenamalhotra dismissed their stale review November 15, 2024 23:15

Will review again new changes

@benrr101

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@paulmedynski

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@codecov

codecov Bot commented Jul 2, 2025 •

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 62.99%. Comparing base (df35633) to head (02046a9).
Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2968      +/-   ##
==========================================
- Coverage   66.91%   62.99%   -3.92%     
==========================================
  Files         280      274       -6     
  Lines       62386    62076     -310     
==========================================
- Hits        41745    39107    -2638     
- Misses      20641    22969    +2328     
Flag Coverage Δ
addons ?
netcore 67.15% <ø> (-1.82%) ⬇️
netfx 62.29% <ø> (-6.96%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@edwardneal
edwardneal requested a review from a team as a code owner July 2, 2025 20:51
@paulmedynski

Copy link
Copy Markdown
Contributor

/azp run

This was referenced Sep 20, 2026
carndog added a commit to carndog/TradingEngine that referenced this pull request Sep 24, 2026
Updated [Microsoft.Data.SqlClient](https://github.com/dotnet/sqlclient)
from 6.1.6 to 7.1.0.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.Data.SqlClient's
releases](https://github.com/dotnet/sqlclient/releases)._

## 7.1.0

This is the general availability release of **Microsoft.Data.SqlClient
7.1**. It closes out the `7.1` preview cycle with application identity
reporting for telemetry, the deprecation of
`TransparentNetworkIPResolution`, and a set of connection, transaction,
and Named Pipes fixes.

> **Important — package version alignment:** Starting with the
[7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.0/7.0.2.md)
release, the `Microsoft.Data.SqlClient` driver and its companion
packages share a single aligned version. The `7.1.0` GA release
continues this alignment; the following packages ship together as
`7.1.0`:
>
> - `Microsoft.Data.SqlClient`
> - `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider`
> - `Microsoft.Data.SqlClient.Extensions.Azure`
> - `Microsoft.Data.SqlClient.Extensions.Abstractions`
> - `Microsoft.Data.SqlClient.Internal.Logging`
>
> (`Microsoft.SqlServer.Server` continues to version independently and
remains at `1.0.0`.)
>
> Applications must reference the same versions of
`Microsoft.Data.SqlClient` and its extensions for best compatibility. In
particular, applications that reference
`Microsoft.Data.SqlClient.Extensions.Azure` must upgrade it to `7.1.0`
when upgrading `Microsoft.Data.SqlClient` to `7.1.0`.
>
> **Compatibility guarantee:** All aligned assemblies ship with
`FileVersion 7.1.0.x` and `AssemblyVersion 7.0.0.0`. The
`AssemblyVersion` is unchanged from
[7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.0/7.0.2.md),
so upgrading from `7.0.2`, `7.0.3`, or any `7.1` preview to `7.1.0` does
**not** require any new .NET Framework strong-name binding redirects.
Applications upgrading from `7.0.0` or `7.0.1` should note that
`Extensions.Azure`, `Extensions.Abstractions`, and `Internal.Logging`
raised their `AssemblyVersion` from `1.0.0.0` to `7.0.0.0` in
[7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.0/7.0.2.md);
see those release notes for the one-time .NET Framework impact.

### Companion package release notes

- [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
7.1.0](https://github.com/dotnet/SqlClient/blob/main/release-notes/add-ons/AzureKeyVaultProvider/7.1/7.1.0.md)
- [Microsoft.Data.SqlClient.Extensions.Azure
7.1.0](https://github.com/dotnet/SqlClient/blob/main/release-notes/Extensions/Azure/7.1/7.1.0.md)
- [Microsoft.Data.SqlClient.Extensions.Abstractions
7.1.0](https://github.com/dotnet/SqlClient/blob/main/release-notes/Extensions/Abstractions/7.1/7.1.0.md)
- [Microsoft.Data.SqlClient.Internal.Logging
7.1.0](https://github.com/dotnet/SqlClient/blob/main/release-notes/Internal/Logging/7.1/7.1.0.md)

## Changes Since
[7.1.0-preview3](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.1/7.1.0-preview3.md)

### Added

#### Application Identity in the USERAGENT Payload

*What Changed:*

- Added a `RegisteredApplication` enum and a matching
`SqlConnection.RegisteredApplication` property that let a library or
tool identify itself to SQL Server through version 2 of the TDS
USERAGENT feature extension. The payload also carries a new driver-owned
64-bit *Driver Properties* flag field; bit 0 reports whether connection
pool V2 is enabled for the process. Both fields are emitted as unpadded
uppercase hexadecimal.
([#​3201](https://github.com/dotnet/SqlClient/issues/3201),
[#​4632](https://github.com/dotnet/SqlClient/pull/4632))

*Who Benefits:*

- Middleware and tooling built on top of the driver — Entity Framework
Core, Semantic Kernel, SQL Server Management Studio, SqlPackage, Data
API Builder, and similar — can be distinguished in server-side telemetry
without the driver accepting arbitrary user-supplied user-agent text.
This originated as a request from the Entity Framework Core team.
- Service operators gain a more accurate picture of which client stacks
are connecting, which helps when diagnosing workload-specific behavior.

*Impact:*

- Purely additive from the application's perspective: a newly created
physical connection whose `RegisteredApplication` is unset reports
`Unknown` (`0`). On the wire the field itself is new — USERAGENT payload
v1 carried no application identifier, while v2 always emits one.
- Set the property before calling `Open` or `OpenAsync`. Assigning it
while the connection is connecting or open throws
`InvalidOperationException`.

```c#
using var connection = new SqlConnection(connectionString);
connection.RegisteredApplication = RegisteredApplication.EntityFrameworkCore;
await connection.OpenAsync();
```

- The enum is `ushort`-backed and marked `[CLSCompliant(false)]`. Values
are partitioned by range: `0x0001`–`0x7FFF` for Microsoft-defined
large-scale applications, `0x8000`–`0xBFFF` for small-scale use, and
`0xC000`–`0xFFFF` for public/developer use. Applications that are not
yet registered can cast an unassigned value from the appropriate range.
 ... (truncated)

## 7.1.0-preview3

This update brings the following changes since the
[7.1.0-preview2](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.1/7.1.0-preview2.md)
release.

> **Package version alignment:** The `Microsoft.Data.SqlClient` driver
and its companion packages continue the aligned versioning introduced in
[7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.0/7.0.2.md).
All five packages listed below ship together as `7.1.0-preview3`.
(`Microsoft.SqlServer.Server` continues to version independently and
remains at `1.0.0`.) Applications that reference
`Microsoft.Data.SqlClient.Extensions.Azure` must upgrade it to
`7.1.0-preview3` when upgrading `Microsoft.Data.SqlClient`.

> **Compatibility guarantee:** All aligned assemblies ship with
`FileVersion 7.1.0.x` and `AssemblyVersion 7.0.0.0` — unchanged from
7.0.2 — so upgrading from `7.0.2` to `7.1.0-preview3` does **not**
require any new .NET Framework strong-name binding redirects.

## Packages in this release

### `Microsoft.Data.SqlClient` 7.1.0-preview3

**Added**
- Asynchronous key store provider APIs for Always Encrypted — four
`virtual` methods on `SqlColumnEncryptionKeyStoreProvider` with
`CancellationToken` support. Purely additive; defaults delegate to the
synchronous methods, so existing providers are unaffected
([#​3672](https://github.com/dotnet/SqlClient/issues/3672),
[#​3673](https://github.com/dotnet/SqlClient/pull/3673))
- Connection Pool V2 nears parity with the default pool (opt-in via
`Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2`):
- Transaction support
([#​4487](https://github.com/dotnet/SqlClient/pull/4487))
- Broken-connection replacement during command execution
([#​4429](https://github.com/dotnet/SqlClient/pull/4429))
- Background warmup to `Min Pool Size` and automatic replenishment
([#​4452](https://github.com/dotnet/SqlClient/pull/4452))
- Idle pruning driven by `Connection Idle Timeout`
([#​4463](https://github.com/dotnet/SqlClient/pull/4463))
- Optional `ConcurrencyLimiter` rate limiting for new physical
connections ([#​4395](https://github.com/dotnet/SqlClient/pull/4395),
[#​4396](https://github.com/dotnet/SqlClient/pull/4396))
- Leaked connection reclamation, including the previously always-zero
`number-of-reclaimed-connections` counter
([#​4529](https://github.com/dotnet/SqlClient/pull/4529))
- Metrics and tracing parity with the default pool
([#​4504](https://github.com/dotnet/SqlClient/pull/4504))

**Changed**
- Single cross-platform build — Windows-only native SNI types now trim
cleanly on Linux and macOS. Package structure and contents unchanged
([#​4207](https://github.com/dotnet/SqlClient/pull/4207),
[#​4239](https://github.com/dotnet/SqlClient/issues/4239),
[#​4465](https://github.com/dotnet/SqlClient/pull/4465),
[#​4474](https://github.com/dotnet/SqlClient/pull/4474))
- Async read-path allocations restored to baseline via `PacketData` node
reuse — `ExecuteReaderAsync` goes from +120.9% to +0.1% against 6.1.6
([#​4536](https://github.com/dotnet/SqlClient/pull/4536))
- `SqlBulkCopy` skips graph alias mapping when no graph pseudo-columns
are present, recovering a regression from
[#​3677](https://github.com/dotnet/SqlClient/pull/3677)
([#​4535](https://github.com/dotnet/SqlClient/pull/4535))
- No formatted trace string is allocated when `SqlClientEventSource`
tracing is disabled, recovering a memory regression against 6.1.6. Trace
output unchanged
([#​4528](https://github.com/dotnet/SqlClient/pull/4528))
- `net9.0` dependencies moved to `9.0.18`;
`System.Threading.RateLimiting` added to packaged metadata. Other
targets keep their `8.0.x` pins
([#​4507](https://github.com/dotnet/SqlClient/pull/4507))
- `Microsoft.Data.SqlClient.SNI` and `.SNI.runtime` updated to
`7.1.0-preview3.26226.3`
([#​4564](https://github.com/dotnet/SqlClient/pull/4564))

**Fixed**
- Always Encrypted VSM/HGS attestation now verifies the enclave public
key is bound to the signed report, using a fixed-time `SHA-256`
comparison against `EnclaveData`
([#​4532](https://github.com/dotnet/SqlClient/pull/4532))
- `SqlConnectionFactory` no longer wakes the process every 30 seconds
when no pools exist — including with `Pooling=False` and after
`ClearAllPools()`
([#​1881](https://github.com/dotnet/SqlClient/issues/1881),
[#​4479](https://github.com/dotnet/SqlClient/pull/4479))
- Connection pool performance counters affecting the **default** pool as
well as pool V2 — `active-soft-connects` and
`number-of-active-connections` could go negative after a failed
activation, and several gauges drifted upward permanently after a broken
connection was replaced
([#​4504](https://github.com/dotnet/SqlClient/pull/4504))
- `OverflowException` when sending large `decimal` values with explicit
`Precision` and `Scale`, which primarily affected Always Encrypted
([#​1655](https://github.com/dotnet/SqlClient/issues/1655),
[#​4443](https://github.com/dotnet/SqlClient/pull/4443))
- TDS stream error when passing a `DateOnly` value with
`SqlDbType.Variant` (net8.0/net9.0)
([#​3953](https://github.com/dotnet/SqlClient/issues/3953),
[#​4294](https://github.com/dotnet/SqlClient/pull/4294))
- `DateOnly` in table-valued parameter `sql_variant` columns sent as
`datetime` instead of `date`, which overflowed for values valid as
`date` (net8.0/net9.0)
([#​3934](https://github.com/dotnet/SqlClient/issues/3934),
[#​4439](https://github.com/dotnet/SqlClient/pull/4439))
- `ServerCertificate` keyword ignored when the platform reported no TLS
policy errors. It is now always compared, and an unloadable certificate
fails closed with `SSLCertificateAuthenticationException` instead of
silently falling back to host-name validation
([#​4445](https://github.com/dotnet/SqlClient/pull/4445))
- `SqlConnection.AccessTokenCallback` not disabling TNIR by default,
plus pool-key construction and `SspiContextProvider` exclusivity with
token auth (net462 for the TNIR behavior)
([#​4520](https://github.com/dotnet/SqlClient/pull/4520))
- Fatal exceptions such as `OutOfMemoryException` captured into faulted
`Task`s across several `SqlBulkCopy`, `SqlDataReader`, and `SqlCommand`
async entry points
([#​4437](https://github.com/dotnet/SqlClient/pull/4437))
- Entra ID authentication failing against multi-segment authorities such
as the Dataverse / Dynamics 365 TDS endpoint. Ships in
`Microsoft.Data.SqlClient.Extensions.Azure`
([#​4496](https://github.com/dotnet/SqlClient/issues/4496),
[#​4521](https://github.com/dotnet/SqlClient/pull/4521))

Full details:
[release-notes/7.1/7.1.0-preview3.md](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.1/7.1.0-preview3.md)

---

### `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider`
7.1.0-preview3

**Added**
- `SqlColumnEncryptionAzureKeyVaultProvider` overrides the four
asynchronous key store provider methods introduced in
[#​3673](https://github.com/dotnet/SqlClient/pull/3673), calling the
Azure SDK's own async APIs and flowing the supplied `CancellationToken`
([#​4540](https://github.com/dotnet/SqlClient/pull/4540))
- Concurrent cache misses for the same key collapse into a single Key
Vault request. The gate is only awaited, so no thread blocks, and misses
for different keys still proceed in parallel
([#​4540](https://github.com/dotnet/SqlClient/pull/4540))
 ... (truncated)

## 7.1.0-preview2

This update brings the following changes since the
[7.1.0-preview1](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.1/7.1.0-preview1.md)
release.

> **Package version alignment:** The `Microsoft.Data.SqlClient` driver
and its companion packages continue the aligned versioning introduced in
[7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.0/7.0.2.md).
All five packages listed below ship together as `7.1.0-preview2`.
(`Microsoft.SqlServer.Server` continues to version independently and
remains at `1.0.0`.) Applications that reference
`Microsoft.Data.SqlClient.Extensions.Azure` must upgrade it to
`7.1.0-preview2` when upgrading `Microsoft.Data.SqlClient`.

> **Compatibility guarantee:** All aligned assemblies ship with
`FileVersion 7.1.0.x` and `AssemblyVersion 7.0.0.0` — unchanged from
7.0.2 — so upgrading from `7.0.2` to `7.1.0-preview2` does **not**
require any new .NET Framework strong-name binding redirects.

## Packages in this release

### `Microsoft.Data.SqlClient` 7.1.0-preview2

**Added**
- `SqlConnection.GetSchemaAsync` overloads with `CancellationToken`
support ([#​3005](https://github.com/dotnet/SqlClient/pull/3005))
- SQL Graph pseudo-column aliases (`$node_id`, `$edge_id`, `$from_id`,
`$to_id`) accepted in `SqlBulkCopy` mappings
([#​3677](https://github.com/dotnet/SqlClient/pull/3677))
- `SqlBatchCommand.CommandBehavior` and
`SqlBatch.ExecuteReader(CommandBehavior)` are now honored
([#​4125](https://github.com/dotnet/SqlClient/pull/4125))
- Configurable idle connection timeout via `Connection Idle Timeout` /
`SqlConnectionStringBuilder.IdleTimeout` (opt-in via
`Switch.Microsoft.Data.SqlClient.UseLegacyIdleTimeoutBehavior=false`)
([#​4295](https://github.com/dotnet/SqlClient/pull/4295))

**Changed**
- `Connect Timeout` now propagates through the pool when
`Switch.Microsoft.Data.SqlClient.UseOverallConnectTimeoutForPoolWait=true`
is set (default off; introduces a `Microsoft.Bcl.TimeProvider`
dependency) ([#​4270](https://github.com/dotnet/SqlClient/pull/4270))
- SQL Server 2025 `json` type added to the `DataTypes` collection
returned by `SqlConnection.GetSchema`
([#​3858](https://github.com/dotnet/SqlClient/pull/3858))
- Internal state-machine hardening via `Interlocked.CompareExchange`
guards ([#​4267](https://github.com/dotnet/SqlClient/pull/4267))
- Internal cleanup of connection-options inheritance and related pool
interfaces ([#​4237](https://github.com/dotnet/SqlClient/pull/4237),
[#​4261](https://github.com/dotnet/SqlClient/pull/4261),
[#​4235](https://github.com/dotnet/SqlClient/pull/4235),
[#​4415](https://github.com/dotnet/SqlClient/pull/4415),
[#​4334](https://github.com/dotnet/SqlClient/pull/4334))
- LCID hardcoded mappings to avoid repeated culture lookups
([#​4212](https://github.com/dotnet/SqlClient/pull/4212))
- Allocation reductions on `SqlErrorCollection` and null-return paths
([#​4157](https://github.com/dotnet/SqlClient/pull/4157),
[#​4099](https://github.com/dotnet/SqlClient/pull/4099),
[#​4102](https://github.com/dotnet/SqlClient/pull/4102))
- Improved `EnclaveDiffieHellmanInfo.Size` accuracy
([#​4346](https://github.com/dotnet/SqlClient/pull/4346))
- `SqlVector<float>` serialization is now explicitly little-endian for
cross-architecture consistency
([#​3861](https://github.com/dotnet/SqlClient/pull/3861))
- Bundled .NET 10 SDK updated to `10.0.300`
([#​4287](https://github.com/dotnet/SqlClient/pull/4287))

**Fixed**
- `NullReferenceException` in `SqlCommand.Cancel()` when the connection
has already been torn down
([#​4372](https://github.com/dotnet/SqlClient/pull/4372))
- Always Encrypted CMK signature verification incorrectly reusing cached
results after a prior failure
([#​4339](https://github.com/dotnet/SqlClient/pull/4339))
- Missing TDS token / feature-ack length bounds checks (spoofing server
could trigger unbounded allocations)
([#​4340](https://github.com/dotnet/SqlClient/pull/4340))
- `SqlBulkCopy` failing in least-privilege environments
([#​4306](https://github.com/dotnet/SqlClient/pull/4306))
- Always Encrypted `CekMdVersion` / `EkValueCount` reads aligned with
the TDS specification
([#​4240](https://github.com/dotnet/SqlClient/pull/4240))
- `LoginWithFailover` parser-state validation
([#​4140](https://github.com/dotnet/SqlClient/pull/4140))
- SPN during login now uses the resolved port instead of instance name
for `Protocol=None` / `Protocol=Admin`
([#​4180](https://github.com/dotnet/SqlClient/pull/4180))
- Race in `SqlConnection.TryOpenInner` that could surface as
`InvalidCastException` now returns a deterministic
`InvalidOperationException`
([#​4179](https://github.com/dotnet/SqlClient/pull/4179))
- Multiple `CancellationTokenSource` leaks in `SqlDataReader`,
`SqlConnection`, `SqlCommand` reconnect paths, and sequential-stream
helpers ([#​4009](https://github.com/dotnet/SqlClient/pull/4009))
- Docs fix for server certificate configuration
([#​4408](https://github.com/dotnet/SqlClient/pull/4408))

**Removed (breaking)**
- SQL Server 7.0 / 2000 code paths removed; `Type System Version=SQL
Server 2000` now throws `ArgumentException` at open. Applications should
switch to `Latest` (or another supported value). No change to
server-version support — 7.0 / 2000 were already rejected during login
version negotiation.
([#​4015](https://github.com/dotnet/SqlClient/pull/4015))

Full details:
[release-notes/7.1/7.1.0-preview2.md](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.1/7.1.0-preview2.md)

---

### `Microsoft.Data.SqlClient.Extensions.Azure` 7.1.0-preview2

**Added — WAM (Windows Account Manager) broker support for Entra ID
authentication (Windows only)**
([#​4288](https://github.com/dotnet/SqlClient/pull/4288),
[#​4388](https://github.com/dotnet/SqlClient/pull/4388))
- Covers `ActiveDirectoryIntegrated`, `ActiveDirectoryInteractive`,
`ActiveDirectoryDeviceCodeFlow`, and the deprecated
`ActiveDirectoryPassword` modes.
 ... (truncated)

## 7.1.0-preview1

This update brings the following changes since the
[7.0.0](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.0/7.0.0.md)
release:

### Added

#### `SqlBatch` Support on .NET Framework

*What Changed:*

- Added `SqlBatch` and related batch-command support for the .NET
Framework target so the batching API is now available across the full
supported platform matrix, including `net462`.
([#​3926](https://github.com/dotnet/SqlClient/pull/3926))

*Who Benefits:*

- Applications that target .NET Framework but also want to use the newer
batching APIs no longer need a separate implementation strategy from
.NET 8/9 applications.
- Libraries that multi-target .NET Framework and modern .NET can use a
more consistent data-access surface area.

*Impact:*

- `SqlBatch`, `SqlBatchCommand`, and the related execution methods are
now usable on .NET Framework builds in addition to .NET.

#### Cross-Driver Connection-String Synonym Alignment

*What Changed:*

- Added additional accepted connection-string synonyms for better
compatibility with other SQL Server drivers and existing
connection-string conventions. Newly accepted synonyms include
`ColumnEncryption`, `ConnectTimeout`, `FailoverPartner`, `PacketSize`,
and `WorkstationId`.
([#​4192](https://github.com/dotnet/SqlClient/pull/4192))

*Who Benefits:*

- Applications migrating connection strings from other SQL Server
drivers or shared infrastructure can reuse more existing keywords
without rewriting them first.

*Impact:*

- Existing canonical keywords continue to work unchanged; this preview
simply accepts more equivalent aliases during parsing.

### Changed
#### Type Forwards for Authentication Abstractions

*What Changed:*

- Added type forwards from the core `Microsoft.Data.SqlClient` assembly
to public authentication-related types that were moved into
`Microsoft.Data.SqlClient.Extensions.Abstractions`, including
`SqlAuthenticationMethod`, `SqlAuthenticationParameters`,
`SqlAuthenticationProvider`, `SqlAuthenticationProviderException`, and
`SqlAuthenticationToken`.
([#​4067](https://github.com/dotnet/SqlClient/pull/4067),
[#​4117](https://github.com/dotnet/SqlClient/pull/4117))

*Who Benefits:*

- Applications and libraries compiled against earlier package layouts
retain binary compatibility when those authentication types are resolved
from the core assembly name.

*Impact:*

- No application code changes are required; the type forwards preserve
existing compiled references.

#### User Agent Feature Extension Enabled by Default

 ... (truncated)

## 7.0.3

This update brings the following changes since the [7.0.2](7.0.2.md)
release:

The core driver and its companion packages ship together as version
`7.0.3`. Update the companion packages you use alongside the driver to
`7.0.3`. Assembly versions remain `7.0.0.0`, unchanged from `7.0.2`.

### Companion package release notes

- [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
7.0.3](../add-ons/AzureKeyVaultProvider/7.0/7.0.3.md)
- [Microsoft.Data.SqlClient.Extensions.Azure
7.0.3](../Extensions/Azure/7.0/7.0.3.md) — includes the Entra ID
authority parsing fix for Dataverse/Dynamics 365 connections.
- [Microsoft.Data.SqlClient.Extensions.Abstractions
7.0.3](../Extensions/Abstractions/7.0/7.0.3.md)
- [Microsoft.Data.SqlClient.Internal.Logging
7.0.3](../Internal/Logging/7.0/7.0.3.md)

### Changed

- Updated the `Microsoft.Data.SqlClient.SNI` and
`Microsoft.Data.SqlClient.SNI.runtime` dependencies to 6.0.3 (was
6.0.2).
  ([#​4599](https://github.com/dotnet/SqlClient/pull/4599))

### Fixed

- Fixed a `SqlBulkCopy` regression in environments where the application
login cannot read `sys.all_columns`. Bulk copy now falls back to the
earlier column-discovery behavior when that permission is unavailable.
Support for hidden columns and SQL Graph column aliases still requires
access to the metadata view.
([#​4370](https://github.com/dotnet/SqlClient/issues/4370),
[#​4306](https://github.com/dotnet/SqlClient/pull/4306),
[#​4402](https://github.com/dotnet/SqlClient/pull/4402))

- Fixed a memory-allocation regression in connection and command
operations caused by formatting diagnostic strings even when tracing was
disabled. Also corrected trace messages that reported an incorrect
object ID or could throw `FormatException` when traced values contained
braces.
([#​4528](https://github.com/dotnet/SqlClient/pull/4528),
[#​4533](https://github.com/dotnet/SqlClient/pull/4533))

- Fixed `ServerCertificate` validation on the managed SNI path so the
configured certificate is compared against the server certificate even
when the server certificate passes chain and host-name validation. When
certificate validation is enabled, a missing, unreadable, or invalid
certificate file, a certificate mismatch, or a missing server
certificate now causes the TLS handshake to fail instead of bypassing
the configured certificate check. (net8.0/net9.0 only)
([#​4445](https://github.com/dotnet/SqlClient/pull/4445),
[#​4583](https://github.com/dotnet/SqlClient/pull/4583))

- Fixed Always Encrypted VSM/HGS enclave attestation to verify that the
enclave public key used to establish a session matches the key committed
to by the signed attestation report. Missing, malformed, or mismatched
key-binding data now causes attestation to fail before the session
secret is derived.
([#​4532](https://github.com/dotnet/SqlClient/pull/4532),
[#​4553](https://github.com/dotnet/SqlClient/pull/4553))

- Fixed `SqlConnection.AccessTokenCallback` not disabling Transparent
Network IP Resolution by default, making it consistent with
`SqlConnection.AccessToken`. An explicitly configured
`TransparentNetworkIPResolution` connection-string value still takes
precedence. (net462 only)
([#​4520](https://github.com/dotnet/SqlClient/pull/4520),
[#​4561](https://github.com/dotnet/SqlClient/pull/4561))

- Fixed authentication state handling so clearing
`SqlConnection.AccessToken`, `AccessTokenCallback`, or
`SspiContextProvider` preserves the other authentication values in the
connection pool key. Cloning a connection or updating its credential
also preserves its `SspiContextProvider`. Combining a non-null
`SspiContextProvider` with `AccessToken` or `AccessTokenCallback` now
throws `InvalidOperationException` instead of silently discarding
authentication state; applications must use one authentication mechanism
at a time.
([#​4520](https://github.com/dotnet/SqlClient/pull/4520),
[#​4561](https://github.com/dotnet/SqlClient/pull/4561),
[#​4644](https://github.com/dotnet/SqlClient/pull/4644))

- Fixed configurable retry logic installing a permanent, process-wide
assembly-resolution handler that could interfere with unrelated assembly
loading. The handler is now active only while an explicitly configured
custom retry provider is resolved and constructed, and probes
`AppContext.BaseDirectory` instead of the current working directory.
Place custom retry assemblies in the application base directory;
dependencies loaded after provider construction must be resolvable
through normal application dependency resolution or an
application-provided handler. (net8.0/net9.0 only)
([#​2214](https://github.com/dotnet/SqlClient/issues/2214),
[#​4547](https://github.com/dotnet/SqlClient/pull/4547),
[#​4663](https://github.com/dotnet/SqlClient/pull/4663))

## Contributors

We thank the following public contributors. Their efforts toward this
project are very much appreciated.

- [edwardneal](https://github.com/edwardneal)

## Target Platform Support

- .NET Framework 4.6.2+ (Windows x86, Windows x64, Windows ARM64)
- .NET 8.0+ (Windows x86, Windows x64, Windows ARM, Windows ARM64,
Linux, macOS)

 ... (truncated)

## 7.0.2

This update brings the following changes since the
[7.0.1](https://github.com/dotnet/SqlClient/blob/main/release-notes/7.0/7.0.1.md)
release:

> **Important — package version alignment:** Starting with 7.0.2, the
`Microsoft.Data.SqlClient` driver and its companion packages share a
single aligned version. The following packages now ship together as
`7.0.2`:
>
> - `Microsoft.Data.SqlClient`
> - `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider`
> - `Microsoft.Data.SqlClient.Extensions.Azure`
> - `Microsoft.Data.SqlClient.Extensions.Abstractions`
> - `Microsoft.Data.SqlClient.Internal.Logging`
>
> (`Microsoft.SqlServer.Server` continues to version independently and
remains at `1.0.0`.)
>
> Applications must reference the same versions of
`Microsoft.Data.SqlClient` and its extensions for best compatibility. In
particular, applications that reference
`Microsoft.Data.SqlClient.Extensions.Azure` must upgrade it to `7.0.2`
when upgrading `Microsoft.Data.SqlClient` to `7.0.2`.

> **Breaking change (.NET Framework only):** As part of this alignment,
the `AssemblyVersion` of `Microsoft.Data.SqlClient.Extensions.Azure`,
`Microsoft.Data.SqlClient.Extensions.Abstractions`, and
`Microsoft.Data.SqlClient.Internal.Logging` changed from `1.0.0.0` to
`7.0.0.0` (the `Microsoft.Data.SqlClient` and
`Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider`
assembly versions are unchanged). On .NET Framework, `AssemblyVersion`
is part of the strong-name identity, so applications that drop these
assemblies into an existing deployment without rebuilding must rebuild
against the 7.0.2 packages (or add binding redirects). Applications on
.NET / .NET Core are not affected.

### Companion package release notes

The following companion packages ship aligned as `7.0.2`. See their
individual release notes for package-specific changes (including the
`Microsoft.Data.SqlClient.Extensions.Azure` WAM broker support):

- [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/add-ons/AzureKeyVaultProvider/7.0/7.0.2.md)
- [Microsoft.Data.SqlClient.Extensions.Azure
7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/Extensions/Azure/7.0/7.0.2.md)
- [Microsoft.Data.SqlClient.Extensions.Abstractions
7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/Extensions/Abstractions/7.0/7.0.2.md)
- [Microsoft.Data.SqlClient.Internal.Logging
7.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/Internal/Logging/7.0/7.0.2.md)

### Fixed

- Fixed a `NullReferenceException` in `SqlCommand.Cancel()`. The
diagnostic message built during cancellation dereferenced the active
connection directly; it now uses a null-conditional access so
cancellation no longer throws when the connection has already been torn
down.

([#​4372](https://github.com/dotnet/SqlClient/pull/4372),[#​4373](https://github.com/dotnet/SqlClient/pull/4373))

- Fixed a `NullReferenceException` in `SqlDataReader` when calling
`GetBytes`/`GetChars` with a `null` destination buffer. The
argument-validation path that constructs the
`InvalidDestinationBufferIndex` exception now guards against the null
buffer so the correct `ArgumentException` is surfaced instead of an NRE.

([#​4159](https://github.com/dotnet/SqlClient/pull/4159),[#​4206](https://github.com/dotnet/SqlClient/pull/4206))

- Fixed Always Encrypted column master key signature verification
incorrectly reusing cached results. The `SignatureVerificationCache`
lookup logic was corrected so signature verification outcomes are cached
and retrieved against the correct key, preventing stale or mismatched
verification results.

([#​4339](https://github.com/dotnet/SqlClient/pull/4339),[#​4343](https://github.com/dotnet/SqlClient/pull/4343))

### Changed

#### Hardened TDS token parsing with data-length bounds checks

*What Changed:*

- Added bounds checking when parsing TDS token and
feature-extension-acknowledgment data lengths. The parser now validates
the declared length of incoming token data against the available buffer
before reading, rejecting malformed or out-of-range length values
instead of reading past the intended boundary.

([#​4340](https://github.com/dotnet/SqlClient/pull/4340),[#​4358](https://github.com/dotnet/SqlClient/pull/4358))

*Who Benefits:*

- All consumers benefit from improved resilience against malformed or
hostile TDS responses. A server (or man-in-the-middle) sending an
invalid token length can no longer drive the parser to read beyond the
declared payload.

*Impact:*
 ... (truncated)

## 7.0.1

This update brings the following changes since the
[7.0.0](https://github.com/dotnet/SqlClient/blob/release/7.0/release-notes/7.0/7.0.0.md)
release:

### Fixed

- Fixed `SqlBulkCopy` failing on SQL Server 2016 with `Invalid column
name 'graph_type'` error. The column metadata query now uses dynamic SQL
so that references to the `graph_type` column (introduced in SQL Server
2017) are not compiled on older versions that lack the column.
([#​3714](https://github.com/dotnet/SqlClient/issues/3714),
[#​4092](https://github.com/dotnet/SqlClient/pull/4092),
[#​4147](https://github.com/dotnet/SqlClient/pull/4147))

- Fixed `SqlBulkCopy` failing on Azure Synapse Analytics dedicated SQL
pools. The column-list query previously used a variable-assignment
pattern that Synapse does not support; it now uses `STRING_AGG` when
targeting Synapse (engine edition 6) and falls back to the
variable-assignment approach for SQL Server 2016 compatibility.
([#​4149](https://github.com/dotnet/SqlClient/issues/4149),
[#​4176](https://github.com/dotnet/SqlClient/pull/4176),
[#​4182](https://github.com/dotnet/SqlClient/pull/4182))

- Fixed `SqlDataReader.GetFieldType()` and
`GetProviderSpecificFieldType()` returning `typeof(byte[])` instead of
`typeof(SqlVector<float>)` for vector float32 columns. The methods now
follow the same type-determination logic as `GetValue()`.
([#​4104](https://github.com/dotnet/SqlClient/issues/4104),
[#​4105](https://github.com/dotnet/SqlClient/pull/4105),
[#​4152](https://github.com/dotnet/SqlClient/pull/4152))

- Added missing `System.Data.Common` (v4.3.0) NuGet package dependency
for .NET Framework consumers. The inbox `System.Data.Common` assembly on
.NET Framework predates APIs such as `IDbColumnSchemaGenerator`; without
the explicit NuGet dependency, consumers encountered `CS0012`
compilation errors when using these types through
`Microsoft.Data.SqlClient`.
([#​4063](https://github.com/dotnet/SqlClient/pull/4063),
[#​4074](https://github.com/dotnet/SqlClient/pull/4074))

### Changed

- Enabled the User Agent TDS feature extension unconditionally. The
`Switch.Microsoft.Data.SqlClient.EnableUserAgent` AppContext switch has
been removed; the driver now always sends User Agent information during
login. ([#​4124](https://github.com/dotnet/SqlClient/pull/4124),
[#​4154](https://github.com/dotnet/SqlClient/pull/4154))

- Added type forwards from the core `Microsoft.Data.SqlClient` assembly
to public types that were moved to the
`Microsoft.Data.SqlClient.Extensions.Abstractions` package:
`SqlAuthenticationMethod`, `SqlAuthenticationParameters`,
`SqlAuthenticationProvider`, `SqlAuthenticationProviderException`, and
`SqlAuthenticationToken`. This ensures binary compatibility for
assemblies compiled against earlier versions of
`Microsoft.Data.SqlClient` where these types lived in the core assembly.
([#​4067](https://github.com/dotnet/SqlClient/pull/4067),
[#​4117](https://github.com/dotnet/SqlClient/pull/4117))

- Fixed API documentation include paths and duplicate doc snippets.
([#​4084](https://github.com/dotnet/SqlClient/pull/4084),
[#​4086](https://github.com/dotnet/SqlClient/pull/4086),
[#​4107](https://github.com/dotnet/SqlClient/pull/4107),
[#​4161](https://github.com/dotnet/SqlClient/pull/4161))

## Contributors

We thank the following public contributors. Their efforts toward this
project are very much appreciated.

- [edwardneal](https://github.com/edwardneal)

## Target Platform Support

- .NET Framework 4.6.2+ (Windows x86, Windows x64, Windows ARM64)
- .NET 8.0+ (Windows x86, Windows x64, Windows ARM, Windows ARM64,
Linux, macOS)

### Dependencies

#### .NET 9.0

- Microsoft.Bcl.Cryptography 9.0.13
- Microsoft.Data.SqlClient.Extensions.Abstractions 1.0.0
- Microsoft.Data.SqlClient.Internal.Logging 1.0.0
- Microsoft.Data.SqlClient.SNI.runtime 6.0.2
- Microsoft.Extensions.Caching.Memory 9.0.13
- Microsoft.IdentityModel.JsonWebTokens 8.16.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 8.16.0
- Microsoft.SqlServer.Server 1.0.0
- System.Configuration.ConfigurationManager 9.0.13
- System.Security.Cryptography.Pkcs 9.0.13

#### .NET 8.0

- Microsoft.Bcl.Cryptography 8.0.0
- Microsoft.Data.SqlClient.Extensions.Abstractions 1.0.0
 ... (truncated)

## 7.0.0

This is the general availability release of **Microsoft.Data.SqlClient
7.0**, a major milestone for the .NET data provider for SQL Server. This
release addresses the most upvoted issue in the repository's history —
extracting Azure dependencies from the core package — introduces
pluggable SSPI authentication, adds enhanced routing for Azure SQL
Hyperscale, and delivers async read performance improvements.

Also released as part of this milestone:
- Released Microsoft.Data.SqlClient.Extensions.Abstractions 1.0.0. See
[release notes](../Extensions/Abstractions/1.0/1.0.0.md).
- Released Microsoft.Data.SqlClient.Extensions.Azure 1.0.0. See [release
notes](../Extensions/Azure/1.0/1.0.0.md).
- Released Microsoft.Data.SqlClient.Internal.Logging 1.0.0. See [release
notes](../Internal/Logging/1.0/1.0.0.md).
- Released
Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 7.0.0.
See [release notes](../add-ons/AzureKeyVaultProvider/7.0/7.0.0.md).

## Changes Since [7.0.0-preview4](7.0.0-preview4.md)

### Added

- Added actionable error message when Entra ID authentication methods
are used without the `Microsoft.Data.SqlClient.Extensions.Azure` package
installed, guiding users to install the correct package.
([#​3962](https://github.com/dotnet/SqlClient/issues/3962),
[#​4046](https://github.com/dotnet/SqlClient/pull/4046))
- Added Azure authentication sample application.
([#​3988](https://github.com/dotnet/SqlClient/pull/3988))

### Changed

#### Other changes

- Renamed the `Microsoft.Data.SqlClient.Extensions.Logging` package to
`Microsoft.Data.SqlClient.Internal.Logging` to indicate it is for
internal use only and should not be referenced directly by application
code. ([#​4038](https://github.com/dotnet/SqlClient/pull/4038))
- Fixed non-localized exception strings.
([#​4022](https://github.com/dotnet/SqlClient/pull/4022))
- Codebase merge and cleanup:
([#​3997](https://github.com/dotnet/SqlClient/pull/3997),
[#​4052](https://github.com/dotnet/SqlClient/pull/4052))
- Various test improvements:
([#​3891](https://github.com/dotnet/SqlClient/pull/3891),
[#​3996](https://github.com/dotnet/SqlClient/pull/3996),
[#​4002](https://github.com/dotnet/SqlClient/pull/4002),
[#​4034](https://github.com/dotnet/SqlClient/pull/4034),
[#​4041](https://github.com/dotnet/SqlClient/pull/4041),
[#​4044](https://github.com/dotnet/SqlClient/pull/4044))
- Documentation improvements (including Entra ID branding updates):
([#​4021](https://github.com/dotnet/SqlClient/pull/4021),
[#​4047](https://github.com/dotnet/SqlClient/pull/4047),
[#​4049](https://github.com/dotnet/SqlClient/pull/4049))
- Updated Dependencies
([#​4045](https://github.com/dotnet/SqlClient/pull/4045)):
  - Updated `Azure.Core` to v1.51.1
  - Updated `Azure.Identity` to v1.18.0
  - Updated `Azure.Security.KeyVault.Keys` to v4.9.0
  - Updated `Microsoft.Extensions.Caching.Memory` to v9.0.13 (.NET 9.0)
  - Updated `Microsoft.IdentityModel.JsonWebTokens` to v8.16.0
  - Updated `Microsoft.IdentityModel.Protocols.OpenIdConnect` to v8.16.0
  - Updated `Microsoft.Bcl.Cryptography` to v9.0.13 (.NET 9.0)
- Updated `System.Configuration.ConfigurationManager` to v9.0.13 (.NET
9.0)
  - Updated `System.Diagnostics.DiagnosticSource` to v10.0.3
  - Updated `System.Security.Cryptography.Pkcs` to v9.0.13 (.NET 9.0)
  - Updated `System.Text.Json` to v10.0.3
  - Updated `System.Threading.Channels` to v10.0.3
  - Updated `System.ValueTuple` to v4.6.2

## Cumulative Changes Since [6.1](../6.1/README.md)

This section summarizes all changes across the 7.0 preview cycle for
users upgrading from the latest 6.1 stable release.

### Changed

#### Azure Dependencies Removed from Core Package

*What Changed:*

- The core `Microsoft.Data.SqlClient` package no longer depends on
`Azure.Core`, `Azure.Identity`, or their transitive dependencies (e.g.,
`Microsoft.Identity.Client`, `Microsoft.Web.WebView2`). Azure Active
Directory / Entra ID authentication functionality
(`ActiveDirectoryAuthenticationProvider` and related types) has been
extracted into a new `Microsoft.Data.SqlClient.Extensions.Azure`
package. ([#​1108](https://github.com/dotnet/SqlClient/issues/1108),
[#​3680](https://github.com/dotnet/SqlClient/pull/3680),
[#​3902](https://github.com/dotnet/SqlClient/pull/3902),
[#​3904](https://github.com/dotnet/SqlClient/pull/3904),
[#​3908](https://github.com/dotnet/SqlClient/pull/3908),
[#​3917](https://github.com/dotnet/SqlClient/pull/3917),
[#​3982](https://github.com/dotnet/SqlClient/pull/3982),
[#​3978](https://github.com/dotnet/SqlClient/pull/3978),
[#​3986](https://github.com/dotnet/SqlClient/pull/3986))
 ... (truncated)

## 7.0.0-preview4

### Changed

#### Azure Dependencies Removed from Core Package

*What Changed:*

- The core `Microsoft.Data.SqlClient` package no longer depends on
`Azure.Core`, `Azure.Identity`, or their transitive dependencies (e.g.,
`Microsoft.Identity.Client`, `Microsoft.Web.WebView2`). Azure Active
Directory / Entra authentication functionality
(`ActiveDirectoryAuthenticationProvider` and related types) has been
extracted into a new `Microsoft.Data.SqlClient.Extensions.Azure` package
that can be installed separately when needed.
([#​1108](https://github.com/dotnet/SqlClient/issues/1108),
[#​3680](https://github.com/dotnet/SqlClient/pull/3680),
[#​3902](https://github.com/dotnet/SqlClient/pull/3902),
[#​3904](https://github.com/dotnet/SqlClient/pull/3904),
[#​3908](https://github.com/dotnet/SqlClient/pull/3908),
[#​3917](https://github.com/dotnet/SqlClient/pull/3917),
[#​3982](https://github.com/dotnet/SqlClient/pull/3982),
[#​3978](https://github.com/dotnet/SqlClient/pull/3978),
[#​3986](https://github.com/dotnet/SqlClient/pull/3986))
- To support this separation, two additional packages were introduced:
`Microsoft.Data.SqlClient.Extensions.Abstractions` (shared types between
the core driver and extensions) and
`Microsoft.Data.SqlClient.Extensions.Logging` (shared ETW tracing
infrastructure).
([#​3626](https://github.com/dotnet/SqlClient/pull/3626),
[#​3628](https://github.com/dotnet/SqlClient/pull/3628),
[#​3967](https://github.com/dotnet/SqlClient/pull/3967))

*Who Benefits:*

- All users benefit from a significantly lighter core package.
Previously, the Azure dependency chain pulled in numerous assemblies
(including `Azure.Core`, `Azure.Identity`, `Microsoft.Identity.Client`,
and `Microsoft.Web.WebView2`) even for applications that only needed
basic SQL Server connectivity. This was the most upvoted open issue in
the repository
([#​1108](https://github.com/dotnet/SqlClient/issues/1108)).
- Users who do not use Azure AD authentication no longer carry
Azure-related assemblies in their build output, reducing deployment size
and eliminating confusion about unexpected dependencies.
- Users who do use Azure AD authentication can now manage Azure
dependency versions independently from the core driver.

*Impact:*

- Applications using Azure AD authentication (e.g.,
`ActiveDirectoryPassword`, `ActiveDirectoryInteractive`,
`ActiveDirectoryDefault`, etc.) must now install the
`Microsoft.Data.SqlClient.Extensions.Azure` NuGet package separately. No
code changes are required beyond adding the package reference.

### Added

#### Expose SSPI Context Provider as Public API

*What Changed:*

- Added the `SspiContextProvider` abstract class and a public
`SspiContextProvider` property on `SqlConnection`, allowing applications
to supply a custom SSPI context provider for integrated authentication.
This enables custom Kerberos ticket negotiation and NTLM
username/password authentication scenarios that the driver does not
natively support.
([#​2253](https://github.com/dotnet/SqlClient/issues/2253),
[#​2494](https://github.com/dotnet/SqlClient/pull/2494))

*Who Benefits:*

- Users authenticating across untrusted domains, non-domain-joined
machines, or cross-platform environments where configuring integrated
authentication on the client is difficult or impossible.
- Users running in containers who need manual Kerberos negotiation
without deploying sidecars or external ticket-refresh mechanisms.
- Users who need NTLM username/password authentication to SQL Server,
which the driver does not provide natively.

*Impact:*

- Applications can set a custom `SspiContextProvider` on `SqlConnection`
before opening the connection. The provider handles the authentication
token exchange during integrated authentication. This is an additive API
— existing authentication behavior is unchanged when no custom provider
is set. See
[SspiContextProvider_CustomProvider.cs](../../doc/samples/SspiContextProvider_CustomProvider.cs)
for a sample implementation.
- **Note:** The `SspiContextProvider` is a part of the connection pool
key. Care should be taken when using this property to ensure the
implementation returns a stable identity per resource.

#### Expose Default Transient Error List

*What Changed:*

- Exposed the default transient error codes list via the new
`SqlConfigurableRetryFactory.BaselineTransientErrors` static property
(returns a `ReadOnlyCollection<int>`), making it easier to extend the
set of transient errors without copy-pasting from the repository source.
([#​3903](https://github.com/dotnet/SqlClient/pull/3903))

*Who Benefits:*

- Developers implementing custom retry logic who want to extend the
built-in transient error list rather than replacing it.

*Impact:*

 ... (truncated)

## 7.0.0-preview3

## Preview Release 7.0.0-preview3.25342.7 - December 8, 2025

### Added

#### Support for .NET 10

*What Changed:*

- Updated pipelines and test suites to compile the driver using the .NET
10 SDK. Cleaned up unnecessary dependency references.
  ([#​3686](https://github.com/dotnet/SqlClient/pull/3686))

*Who Benefits:*

- Developers targeting .NET 10.

*Impact:*

- Addressed .NET 10 warnings regarding unused/unnecessary dependencies.

#### Enable SqlClientDiagnosticListener in SqlCommand on .NET Framework

*What Changed:*

- Enabled SqlClientDiagnosticListener functionality on SqlCommand for
.NET Framework.
  ([#​3658](https://github.com/dotnet/SqlClient/pull/3658))

*Who Benefits:*

- Developers requiring diagnostic information on .NET Framework.

*Impact:*

- Improved observability and diagnostics for SqlCommand on .NET
Framework.

#### Enable User Agent Extension

*What Changed:*

- Enabled User Agent Feature Extension.
  ([#​3606](https://github.com/dotnet/SqlClient/pull/3606))

*Who Benefits:*

- Telemetry and diagnostics consumers.

*Impact:*

- When the `Switch.Microsoft.Data.SqlClient.EnableUserAgent` app context
switch is enabled, the driver sends more detailed user agent strings.
This switch is disabled by default. This change will assist with
troubleshooting and quantifying driver usage by version and operating
system.

### Fixed
 ... (truncated)

## 7.0.0-preview2

This update brings the following changes since the
[7.0.0-preview1](7.0.0-preview1.md) release:

### Bug Fixes

- Fixed a debug assertion in connection pool (no impact to production
code) ([#​3587](https://github.com/dotnet/SqlClient/pull/3587))
- Prevent uninitialized performance counters escaping
`CreatePerformanceCounters`
([#​3623](https://github.com/dotnet/SqlClient/pull/3623))
- Fix SetProvider to return immediately if user-defined authentication
provider found ([#​3620](https://github.com/dotnet/SqlClient/pull/3620))
- Allow SqlBulkCopy to operate on hidden columns
([#​3590](https://github.com/dotnet/SqlClient/pull/3590))
- Fix connection pool concurrency issue
([#​3632](https://github.com/dotnet/SqlClient/pull/3632))

### Added

#### App Context Switch for Ignoring Server-Provided Failover Partner

*What Changed:*

- A new app context switch
`Switch.Microsoft.Data.SqlClient.IgnoreServerProvidedFailoverPartner`
was introduced to let the client ignore server-provided failover partner
info in Basic Availability Groups (BAGs). When the switch is enabled,
only the failover partner specified in the connection string is used;
server-supplied partner values are skipped. This context switch was
introduced in PR
[#​3625](https://github.com/dotnet/SqlClient/pull/3625).

*Who Benefits:*

- Applications connecting to SQL Server BAGs using TCP and custom ports,
especially where the server's provided partner name lacks the protocol,
host, or port. This avoids connection failures when the server-provided
partner is incompatible or incomplete.
- Teams who manage availability groups and rely on client-side control
of failover behavior in heterogeneous networking environments.

*Impact:*

- If your environment might be affected (i.e., you operate a BAG with
custom ports, or have experienced failures after failover), you can
enable the new switch in your application:

```
AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.IgnoreServerProvidedFailoverPartner", true);
```

- Then, ensure your connection string includes your preferred failover
partner (with correct `tcp:host,port`) so that the client uses that
instead of the server's suggestion.
- Without enabling this, by default, the client continues to prefer the
server-provided partner, maintaining backwards compatibility.

#### Other Additions

- Add app context switch for enabling asynchronous multi-packet
improvements ([#​3605](https://github.com/dotnet/SqlClient/pull/3605))

### Changed

#### Deprecation of `SqlAuthenticationMethod.ActiveDirectoryPassword`

*What Changed:*

- Username/Password authentication for Microsoft Entra (formerly Active
Directory) has been deprecated.
`SqlAuthenticationMethod.ActiveDirectoryPassword` is now marked as
`[Obsolete]`. This change occurred in PR
[#​3671](https://github.com/dotnet/SqlClient/pull/3671)

*Who benefits:*

- Teams moving toward stronger, passwordless or MFA-compliant auth (in
line with changes across MSAL/Azure.Identity and Entra MFA enforcement).
This aligns Microsoft.Data.SqlClient with Microsoft's direction to avoid
username/password (ROPC) flows. See
https://learn.microsoft.com/en-us/entra/identity/authentication/concept-mandatory-multifactor-authentication
for more explanation of why this change is being made across Microsoft
products/services.

 ... (truncated)

## 7.0.0-preview1

## Changes Since
[6.1.0](https://github.com/dotnet/SqlClient/blob/main/release-notes/6.1/6.1.0.md)

This update brings the following changes since the
[6.1.0](https://github.com/dotnet/SqlClient/blob/main/release-notes/6.1/6.1.0.md)
release:

### Breaking Changes

- Removed `Constrained Execution Region` error handling blocks and
associated `SqlConnection` cleanup which may affect how
potentially-broken connections are expunged from the pool.
([#​3535](https://github.com/dotnet/SqlClient/pull/3535))

### Bug Fixes

- Packet multiplexing disabled by default, and several bug fixes.
([#​3534](https://github.com/dotnet/SqlClient/pull/3534),
[#​3537](https://github.com/dotnet/SqlClient/pull/3537))

### Added

- `SqlColumnEncryptionCertificateStoreProvider` now works on Windows,
Linux, and macOS.
([#​3014](https://github.com/dotnet/SqlClient/pull/3014))

### Changed

- Updated `SqlVector.Null` to return a nullable `SqlVector` instance in
the reference API to match the implementation.
([#​3521](https://github.com/dotnet/SqlClient/pull/3521))

- Performance improvements for all built-in
`SqlColumnEncryptionKeyStoreProvider` implementations.
([#​3554](https://github.com/dotnet/SqlClient/pull/3554))

- Various test improvements.
([#​3456](https://github.com/dotnet/SqlClient/pull/3456),
[#​2968](https://github.com/dotnet/SqlClient/pull/2968),
[#​3458](https://github.com/dotnet/SqlClient/pull/3458),
[#​3494](https://github.com/dotnet/SqlClient/pull/3494),
[#​3559](https://github.com/dotnet/SqlClient/pull/3559),
[#​3575](https://github.com/dotnet/SqlClient/pull/3575))

- Codebase merge project and related cleanup.
([#​3436](https://github.com/dotnet/SqlClient/pull/3436),
[#​3434](https://github.com/dotnet/SqlClient/pull/3434),
[#​3448](https://github.com/dotnet/SqlClient/pull/3448),
[#​3454](https://github.com/dotnet/SqlClient/pull/3454),
[#​3462](https://github.com/dotnet/SqlClient/pull/3462),
[#​3435](https://github.com/dotnet/SqlClient/pull/3435),
[#​3492](https://github.com/dotnet/SqlClient/pull/3492),
[#​3473](https://github.com/dotnet/SqlClient/pull/3473),
[#​3469](https://github.com/dotnet/SqlClient/pull/3469),
[#​3394](https://github.com/dotnet/SqlClient/pull/3394),
[#​3493](https://github.com/dotnet/SqlClient/pull/3493),
[#​3593](https://github.com/dotnet/SqlClient/pull/3593))

- Documentation improvements.
([#​3490](https://github.com/dotnet/SqlClient/pull/3490))

- Updated `Azure.Identity` dependency to v1.14.2.
([#​3538](https://github.com/dotnet/SqlClient/pull/3538))

## Changes Since
[6.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/6.0/6.0.2.md)

This update brings the following changes since the
[6.0.2](https://github.com/dotnet/SqlClient/blob/main/release-notes/6.0/6.0.2.md)
release. Changes already noted above are omitted:

### Additions

#### Added dedicated SQL Server vector datatype support

*What Changed:*

- Optimized vector communications between MDS and SQL Server 2025,
employing a custom binary format over the TDS protocol.
([#​3433](https://github.com/dotnet/SqlClient/pull/3433),
[#​3443](https://github.com/dotnet/SqlClient/pull/3443))
- Reduced processing load compared to existing JSON-based vector
support.
- Initial support for 32-bit single-precision floating point vectors.

*Who Benefits:*

- Applications moving large vector data sets will see beneficial
improvements to processing times and memory requirements.
- Vector-specific APIs are ready to support future numeric
representations with a consistent look-and-feel.

*Impact:*
 ... (truncated)

## 6.1.7

This update brings the following changes since the [6.1.6](6.1.6.md)
release:

### Changed

- Updated the `Microsoft.Data.SqlClient.SNI` and
`Microsoft.Data.SqlClient.SNI.runtime` dependencies to 6.0.3 (was
6.0.2).
  ([#​4598](https://github.com/dotnet/SqlClient/pull/4598))

### Fixed

- Fixed `ServerCertificate` validation on the managed SNI path so the
configured certificate is compared against the server certificate even
when the server certificate passes chain and host-name validation. When
certificate validation is enabled, a missing, unreadable, or invalid
certificate file, a certificate mismatch, or a missing server
certificate now causes the TLS handshake to fail instead of bypassing
the configured certificate check. (net8.0/net9.0 only)
([#​4445](https://github.com/dotnet/SqlClient/pull/4445),
[#​4584](https://github.com/dotnet/SqlClient/pull/4584))

- Fixed Always Encrypted VSM/HGS enclave attestation to verify that the
enclave public key used to establish a session matches the key committed
to by the signed attestation report. Missing, malformed, or mismatched
key-binding data now causes attestation to fail before the session
secret is derived.
([#​4532](https://github.com/dotnet/SqlClient/pull/4532),
[#​4552](https://github.com/dotnet/SqlClient/pull/4552))

- Fixed `SqlConnection.AccessTokenCallback` not disabling Transparent
Network IP Resolution by default, making it consistent with
`SqlConnection.AccessToken`. An explicitly configured
`TransparentNetworkIPResolution` connection-string value still takes
precedence. (net462 only)
([#​4520](https://github.com/dotnet/SqlClient/pull/4520),
[#​4560](https://github.com/dotnet/SqlClient/pull/4560))

- Fixed token authentication state handling so clearing
`SqlConnection.AccessToken` preserves an existing `AccessTokenCallback`
in the connection pool key, and clearing `AccessTokenCallback` preserves
an existing `AccessToken`. Callback-based authentication now also
follows the same prelogin server-certificate validation rules as an
explicitly supplied access token.
([#​4520](https://github.com/dotnet/SqlClient/pull/4520),
[#​4560](https://github.com/dotnet/SqlClient/pull/4560))

- Fixed configurable retry logic installing a permanent, process-wide
assembly-resolution handler that could interfere with unrelated assembly
loading. The handler is now active only while an explicitly configured
custom retry provider is resolved and constructed, and probes
`AppContext.BaseDirectory` instead of the current working directory.
Place custom retry assemblies in the application base directory;
dependencies loaded after provider construction must be resolvable
through normal application dependency resolution or an
application-provided handler. (net8.0/net9.0 only)
([#​2214](https://github.com/dotnet/SqlClient/issues/2214),
[#​4547](https://github.com/dotnet/SqlClient/pull/4547),
[#​4664](https://github.com/dotnet/SqlClient/pull/4664))

## Target Platform Support

- .NET Framework 4.6.2+ (Windows x86, Windows x64, Windows ARM64)
- .NET 8.0+ (Windows x86, Windows x64, Windows ARM64, Linux, macOS)
- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Linux,
macOS)

Full details:
[release-notes/6.1/6.1.7.md](https://github.com/dotnet/SqlClient/blob/main/release-notes/6.1/6.1.7.md)

Commits viewable in [compare
view](https://github.com/dotnet/sqlclient/compare/v6.1.6...v7.1.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.Data.SqlClient&package-manager=nuget&previous-version=6.1.6&new-version=7.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jason Carney <jason.carney1@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area\Tests Issues that are targeted to tests or test projects

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants