Repository navigation
Stable Release v7.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 release, the
Microsoft.Data.SqlClientdriver and its companion packages share a single aligned version. The7.1.0GA release continues this alignment; the following packages ship together as7.1.0:
Microsoft.Data.SqlClientMicrosoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProviderMicrosoft.Data.SqlClient.Extensions.AzureMicrosoft.Data.SqlClient.Extensions.AbstractionsMicrosoft.Data.SqlClient.Internal.Logging(
Microsoft.SqlServer.Servercontinues to version independently and remains at1.0.0.)Applications must reference the same versions of
Microsoft.Data.SqlClientand its extensions for best compatibility. In particular, applications that referenceMicrosoft.Data.SqlClient.Extensions.Azuremust upgrade it to7.1.0when upgradingMicrosoft.Data.SqlClientto7.1.0.Compatibility guarantee: All aligned assemblies ship with
FileVersion 7.1.0.xandAssemblyVersion 7.0.0.0. TheAssemblyVersionis unchanged from 7.0.2, so upgrading from7.0.2,7.0.3, or any7.1preview to7.1.0does not require any new .NET Framework strong-name binding redirects. Applications upgrading from7.0.0or7.0.1should note thatExtensions.Azure,Extensions.Abstractions, andInternal.Loggingraised theirAssemblyVersionfrom1.0.0.0to7.0.0.0in 7.0.2; see those release notes for the one-time .NET Framework impact.
Companion package release notes
- Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 7.1.0
- Microsoft.Data.SqlClient.Extensions.Azure 7.1.0
- Microsoft.Data.SqlClient.Extensions.Abstractions 7.1.0
- Microsoft.Data.SqlClient.Internal.Logging 7.1.0
Changes Since 7.1.0-preview3
Added
Application Identity in the USERAGENT Payload
What Changed:
- Added a
RegisteredApplicationenum and a matchingSqlConnection.RegisteredApplicationproperty 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, #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
RegisteredApplicationis unset reportsUnknown(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
OpenorOpenAsync. Assigning it while the connection is connecting or open throwsInvalidOperationException.
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–0x7FFFfor Microsoft-defined large-scale applications,0x8000–0xBFFFfor small-scale use, and0xC000–0xFFFFfor public/developer use. Applications that are not yet registered can cast an unassigned value from the appropriate range. - Application identity is client-supplied telemetry and must never be used for authorization or any other security decision.
- The value is not part of the connection pool key. A pooled physical connection reports the application that originally created it, and background
Min Pool Sizeconnections reportUnknown. Cloned connections preserve the value.
Changed
TransparentNetworkIPResolution Is Now Obsolete
What Changed:
SqlConnectionStringBuilder.TransparentNetworkIPResolutionis now marked[Obsolete]. The obsoletion message directs callers toMultiSubnetFailoverand notes that Transparent Network IP Resolution (TNIR) is a .NET Framework-only feature. (#4494, #4576)
Who Benefits:
- Applications still relying on TNIR get a compile-time signal to move to
MultiSubnetFailover, which addresses the same "connect quickly across multiple DNS-resolved addresses" goal, works consistently on every supported target framework, and is the documented strategy for Always On availability group listeners.
Impact:
- No runtime behavior change. TNIR still defaults to
trueon .NET Framework, andMultiSubnetFailoverstill defaults tofalse. The property remains .NET Framework-only and is not exposed on modern .NET, where a connection string containing theTransparent Network IP Resolutionkeyword still throwsNotSupportedException. No new AppContext switches were introduced. - The only visible effect is a new
CS0618build warning for code that references the property. Suppress it, or migrate toMultiSubnetFailover, at your own pace. Flipping the TNIR andMultiSubnetFailoverdefaults is deferred to a future major version.
Other changes
- Updated
Microsoft.Data.SqlClient.SNIandMicrosoft.Data.SqlClient.SNI.runtimeto v7.1.0 (was v7.1.0-preview3.26226.3). (#4698) - Unified the exception message raised when conflicting token-based and SSPI authentication properties are set on the same
SqlConnection, and documented the complete set of properties that conflict withAccessToken. (#4629) - Documentation corrections:
- Rewrote the
SqlDataRecordandSqlMetaDatadocumentation, which incorrectly described the SQL CLR-onlySqlContextandSqlPipetypes, and clarified whetherSqlDataRecordinstances can be reused. (#1805, #4440) - Corrected the LCID 1033 sample comment to use the official Windows locale name
English (United States). (#4646)
- Rewrote the
Fixed
- Fixed a pooled connection being returned to the pool in a broken state after a
TransactionScoperollback — for example, when distributed transaction promotion fails on .NET 8+ where implicit distributed transactions are disabled by default. A subsequentOpen()succeeded butBeginTransaction()threwInvalidOperationException("the connection has been broken"). Connection reset now preserves the transaction when the pooled connection is either a delegated transaction root or enlisted in a transaction, instead of only the latter. (#4001, #4557) - Fixed
GetSchema("DataTypes")never reporting the SQL Server 2025jsontype against Azure SQL. The row was filtered by a string comparison against a minimum server version of17.00.000.0, which Azure SQL can never satisfy because it always reports12.00.xxxx. The decision now uses thejsonsupport flag negotiated through the TDSFEATUREEXTACKtoken, which is accurate on both Azure SQL and on-premises SQL Server 2025+. (#4592, #4682) - Fixed a malformed UNC pipe path being composed for IPv6 literal server names over Named Pipes in managed SNI (for example
Server=np:::1,Server=np:[::1], orServer=\\::1\pipe\sql\query). A UNC path component may not contain a colon, and handing such a path to the OS could trigger an access violation inside LSASS on Windows, forcing a reboot. IPv6 literals are now transcribed to their.ipv6-literal.netform as defined by MS-DTYP 2.2.57, and a colon-bearing host with no valid IPv6 interpretation now fails with the standard invalid-connection-string error. Colon-free host names, LocalDB,localhost,., and IPv6 over TCP are unaffected. (net8.0/net9.0 only — this is the managed SNI counterpart to the native SNI fix) (#4523, #4558) - Fixed configurable retry logic installing a permanent, process-wide assembly-resolution handler that could interfere with unrelated assembly loading. The handler is now installed only while an explicitly configured custom retry provider is being resolved and constructed, and it probes
AppContext.BaseDirectoryinstead 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-supplied handler. (net8.0/net9.0 only — the .NET Framework path does not useAssemblyLoadContext) (#2214, #4547) - Fixed open/close throughput regressions in the opt-in connection pool V2 (
Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2). Acquiring an already-pooled connection no longer dispatches to the thread pool before attempting an inline, non-blocking acquisition, no longer allocates a timer-backedCancellationTokenSourcebefore it is known that the caller will wait, and no longer allocates aTaskon the synchronous completion path. The default pool is unaffected. (#4543)
Cumulative Changes Since 7.0.3
This section summarizes all changes across the 7.1 preview cycle for users upgrading from the latest 7.0 stable release. Changes that were also serviced into 7.0.1, 7.0.2, or 7.0.3 are omitted — they are already present for 7.0.x users.
Added
SqlBatch Support on .NET Framework (net462 only)
What Changed:
SqlBatch,SqlBatchCommand, and the related execution methods are now available on the .NET Framework target, so the batching API spans the full supported platform matrix. (#3926)
Who Benefits:
- Libraries and applications that multi-target .NET Framework and modern .NET can use a single data-access surface instead of maintaining separate batching strategies.
Impact:
- Purely additive; existing
SqlCommandcode is unchanged.
SqlConnection.GetSchemaAsync
What Changed:
- Added asynchronous overloads of
SqlConnection.GetSchemathat mirror the existing synchronous shapes and honor a suppliedCancellationToken. The .NET Framework schema code paths were unified with the .NET implementation in the process. (#3005)
Who Benefits:
- Applications that enumerate database metadata as part of a request pipeline no longer block a thread on synchronous I/O.
Impact:
- Additive; existing
GetSchema(...)calls are unchanged.
Asynchronous Key Store Provider APIs for Always Encrypted
What Changed:
- Added four
virtualasynchronous counterparts to the synchronous methods onSqlColumnEncryptionKeyStoreProvider:DecryptColumnEncryptionKeyAsync,EncryptColumnEncryptionKeyAsync,SignColumnMasterKeyMetadataAsync, andVerifyColumnMasterKeyMetadataAsync. Each accepts an optionalCancellationToken, and the default implementations delegate to the existing synchronous methods. (#3672, #3673)
Who Benefits:
- Authors of custom key store providers backed by network-bound stores such as HSMs or cloud key vaults can implement genuinely asynchronous key operations.
Impact:
- Purely additive; existing providers compile and run unmodified.
- Introduced, but not yet consumed by the driver. The driver's own column encryption key resolution path still invokes the synchronous provider methods on both the synchronous and asynchronous command paths. A future release will enable their use from the driver's own asynchronous APIs.
- The in-box
SqlColumnEncryptionAzureKeyVaultProvideroverrides all four methods. See the AzureKeyVaultProvider 7.1.0 release notes. (#4540)
Configurable Idle Connection Timeout
What Changed:
- Added a
Connection Idle Timeoutconnection-string keyword and matchingSqlConnectionStringBuilder.IdleTimeoutproperty that let the pool evict connections whose idle time exceeds the configured value. The default is300seconds;0disables idle expiration and negative values throwArgumentException. Enforcement is gated onSwitch.Microsoft.Data.SqlClient.UseLegacyIdleTimeoutBehavior, which defaults totrueto preserve historical pooling behavior. (#4295)
Who Benefits:
- Applications running against Azure SQL Database and other elastic backends can bound connection idle time to align with server-side session recycling and reduce stale-connection failures.
Impact:
- Default behavior is unchanged: the keyword is parsed but not enforced until the legacy switch is set to
false.
Connection Pool V2 Feature Completeness
What Changed:
- Substantially expanded
ChannelDbConnectionPool, the opt-in pool behindSwitch.Microsoft.Data.SqlClient.UseConnectionPoolV2, bringing it to parity with the defaultWaitHandleDbConnectionPool: transaction support, broken-connection replacement, background warmup and replenishment toMin Pool Size, idle pruning derived fromConnection Idle Timeout, optional connection-creation rate limiting, leaked-connection reclamation, and metrics/tracing parity. (#4395, #4396, #4429, #4452, #4463, #4487, #4504, #4529, #4543) SqlConnection.ClearPool(SqlConnection)andSqlConnection.ClearAllPools()now work correctly under pool V2. (#4194)
Who Benefits:
- Applications evaluating the V2 pool can exercise transaction-enlisted workloads, broken-connection recovery, leaked-connection reclamation, and pool warmup, and can observe the pool through the existing performance counters and EventSource traces.
Impact:
- No change to default behavior. Connection pool V2 remains in evaluation and is used only when the AppContext switch is enabled.
Other additions
- Added application identity reporting through
SqlConnection.RegisteredApplicationand USERAGENT payload version 2 (see Changes Since 7.1.0-preview3 above). (#4632) SqlBulkCopycolumn mappings now accept the SQL Graph pseudo-column aliases$node_id,$edge_id,$from_id, and$to_idas destination column names. (#3677)SqlBatchCommand.CommandBehavioris now honored inside aSqlBatch, andSqlBatch.ExecuteReaderrespects theCommandBehaviorpassed to it. Batches that previously set the property and relied on it being ignored will now see it applied. (#4125)- Added connection-string synonyms for better compatibility with other SQL Server drivers:
ColumnEncryption,ConnectTimeout,FailoverPartner,PacketSize, andWorkstationId. (#4192) - Added the SQL Server 2025
jsondata type to theDataTypescollection returned bySqlConnection.GetSchema. (#3858)
Changed
Connection Timeout Can Now Propagate Through the Pool
What Changed:
- Replaced raw
TimeSpantimeouts with a sharedTimeoutTimeracrossSqlConnection.Open[Async], pool acquisition, and physical connection creation, so theConnect Timeoutbudget can be deducted while a request waits in the pool. Enforcement is gated onSwitch.Microsoft.Data.SqlClient.UseOverallConnectTimeoutForPoolWait, which defaults tofalse. Introduces a dependency onMicrosoft.Bcl.TimeProvider. (#4270)
Who Benefits:
- Applications that observe pool contention can opt in to having the configured
Connect Timeoutrespected end-to-end instead of the budget effectively restarting when a physical connection is eventually opened.
Impact:
- Default behavior is unchanged. When the switch is enabled,
Open/OpenAsyncunder heavy pool contention may surface timeouts sooner than before; successful opens are unaffected.
TransparentNetworkIPResolution Is Now Obsolete
Other changes
- Windows-only native SNI types are now removed cleanly by the IL trimmer on Linux and macOS, and
LocalAppContextSwitches.UseManagedNetworkingis substituted for a constant. The driver builds a single OS-agnostic assembly for all platforms; NuGet package structure and contents are unchanged. (#4207, #4239, #4465, #4474) - Performance and allocation improvements:
- Restored reuse of
PacketDatalinked-list nodes via a bounded free list onStateSnapshot, returningSqlCommand/ExecuteReaderAsyncfrom +120.9% allocated against the 6.1.6 baseline to +0.1%. (#4536) SqlBulkCopyno longer builds SQL Graph column alias mapping tables when neither the source nor destination table contains graph pseudo-columns. (#4535)- Reduced allocations when sending large string values to SQL Server, when reading
SqlErrorCollectioncounters with no errors present, and on expectednull-return paths that previously materialized stack traces. (#4072, #4157, #4099, #4102) - Use hardcoded LCID mappings when decoding strings, avoiding repeated culture lookups. (#4212)
- Restored reuse of
- Internal hardening and refactoring:
SqlConnectioninternal state transitions now useInterlocked.CompareExchangeguards. (#4267)- Removed legacy connection-options inheritance from internal APIs and refactored
ForceNewConnectionhandling. (#4235, #4237, #4261, #4415) - Added async generic helpers to reduce duplication across sync/async code paths. (#4334)
SqlVector<float>now serializes and deserializes little-endian multibyte values explicitly for consistent behavior across architectures. (#3861)- Improved
EnclaveDiffieHellmanInfo.Sizeaccuracy. (#4346) - Documentation corrections for
SqlDataRecord,SqlMetaData, server certificate configuration, and the LCID 1033 locale name. (#4408, #4440, #4646) - Updated Dependencies:
- Updated
Microsoft.Bcl.Cryptography,Microsoft.Extensions.Caching.Memory,System.Configuration.ConfigurationManager, andSystem.Security.Cryptography.Pkcsto v9.0.18 for thenet9.0target framework. Non-net9.0targets keep their existing8.0.xpins. (#4507) - Added
System.Threading.RateLimitingandMicrosoft.Bcl.TimeProviderto the packaged dependency metadata. (#4270, #4507) - Updated
Microsoft.Data.SqlClient.SNIandMicrosoft.Data.SqlClient.SNI.runtimeto v7.1.0 (was v6.0.3). (#4564, #4698)
- Updated
Fixed
- Fixed Always Encrypted reads of
CekMdVersionandEkValueCountto align with the TDS specification. (#4240) - Fixed an
OverflowExceptionwhen sending largedecimalvalues (for exampledecimal.MaxValue) as a parameter with explicitPrecisionandScale. This primarily affected Always Encrypted scenarios, where both must always be set. (#1655, #4443) - Fixed a TDS stream error when passing a
DateOnlyvalue as a parameter withSqlDbType.Variant, and fixedDateOnlyvalues written to asql_variantcolumn of a table-valued parameter being sent asdatetimeinstead ofdate(which also caused overflows for values valid fordatebut out of range fordatetime). Reading continues to returnDateTimeinstances by default for backwards compatibility. (net8.0/net9.0 only — .NET Framework has noDateOnlytype) (#3953, #3934, #4294, #4439) - Fixed a
SqlConnectionFactorytimer that woke the process every 30 seconds for the lifetime of the application even when no connection pools existed — including withPooling=Falseand afterClearAllPools(). The pruning timer is now armed on demand and disarmed once there is nothing left to prune. A missing .NET Framework unload hook was also added. (#1881, #4479) - Fixed connection pool performance counter defects affecting the default pool as well as pool V2.
active-soft-connectsandnumber-of-active-connectionscould go negative after a failed connection activation, andactive-soft-connects,active-hard-connections, andnumber-of-pooled-connectionsdrifted upward permanently after a broken connection was replaced. (#4504) - Fixed a pooled connection being returned to the pool in a broken state after a
TransactionScoperollback, which caused a laterBeginTransaction()to throwInvalidOperationException. (#4001, #4557) - Fixed
GetSchema("DataTypes")never reporting thejsontype against Azure SQL. (#4592, #4682) - Fixed a malformed UNC pipe path being composed for IPv6 literal server names over Named Pipes in managed SNI, which could trigger an LSASS access violation and a forced reboot on Windows. (net8.0/net9.0 only) (#4523, #4558)
- Fixed several async entry points in
SqlBulkCopy,SqlDataReader.InvokeAsyncCall,SqlCommand.Reader, andSqlCommand.Xmlthat captured fatal exceptions such asOutOfMemoryExceptioninto faultedTasks instead of letting them propagate. (#4437) - Fixed a
SqlDataReaderstreaming bug where callingIsDBNull()before reading a streamed value could skip column data. (#4082) - Fixed a race in
SqlConnection.TryOpenInnerthat could surface asInvalidCastException; the same race now returns a deterministicInvalidOperationException. (#4179) - Fixed
LoginWithFailoverto validate parser state before continuing, preventing null-reference failures during failover login. (#4140) - Fixed the SPN used during login to use the resolved port instead of the instance name when
Protocol=NoneorProtocol=Adminis specified. (#4180) - Fixed several
CancellationTokenSourceleaks inSqlDataReader,SqlConnection, theSqlCommandreconnect paths, and the sequential-stream helpers. (#4009)
Removed
SQL Server 7.0 and 2000 Support
What Changed:
- Removed dead protocol-level code paths for SQL Server 7.0 and SQL Server 2000, along with the now-orphaned
SQL Server 2000type-system compatibility option. TheTypeSystem.SQLServer2000enum value and theType System Version=SQL Server 2000connection-string branch are gone. (#4015)
Who Benefits:
- The driver no longer carries dead legacy code, and the documented connection-string surface (
Latest,SQL Server 2005,SQL Server 2008,SQL Server 2012) now matches the implementation exactly.
Impact:
- Breaking: A connection string that specifies
Type System Version=SQL Server 2000now throwsArgumentExceptionwhen the connection is opened. Switch to a supported value such asLatest. There is no change to which servers the driver connects to — SQL Server 7.0 and 2000 were already rejected during login version negotiation.
Contributors
We thank the following public contributors. Their efforts toward this project are very much appreciated.
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.18
- Microsoft.Data.SqlClient.Extensions.Abstractions 7.1.0
- Microsoft.Data.SqlClient.Internal.Logging 7.1.0
- Microsoft.Data.SqlClient.SNI.runtime 7.1.0
- Microsoft.Extensions.Caching.Memory 9.0.18
- Microsoft.IdentityModel.JsonWebTokens 8.16.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 8.16.0
- Microsoft.SqlServer.Server 1.0.0
- System.Configuration.ConfigurationManager 9.0.18
- System.Security.Cryptography.Pkcs 9.0.18
- System.Threading.RateLimiting 9.0.18
.NET 8.0
- Microsoft.Bcl.Cryptography 8.0.0
- Microsoft.Data.SqlClient.Extensions.Abstractions 7.1.0
- Microsoft.Data.SqlClient.Internal.Logging 7.1.0
- Microsoft.Data.SqlClient.SNI.runtime 7.1.0
- Microsoft.Extensions.Caching.Memory 8.0.1
- Microsoft.IdentityModel.JsonWebTokens 8.16.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 8.16.0
- Microsoft.SqlServer.Server 1.0.0
- System.Configuration.ConfigurationManager 8.0.1
- System.Security.Cryptography.Pkcs 8.0.1
- System.Threading.RateLimiting 8.0.0
.NET Standard 2.0
- Microsoft.Bcl.Cryptography 8.0.0
- Microsoft.Bcl.TimeProvider 8.0.1
- Microsoft.Data.SqlClient.Extensions.Abstractions 7.1.0
- Microsoft.Data.SqlClient.Internal.Logging 7.1.0
- Microsoft.Data.SqlClient.SNI.runtime 7.1.0
- Microsoft.Extensions.Caching.Memory 8.0.1
- Microsoft.IdentityModel.JsonWebTokens 8.16.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 8.16.0
- Microsoft.SqlServer.Server 1.0.0
- System.Configuration.ConfigurationManager 8.0.1
- System.Security.Cryptography.Pkcs 8.0.1
- System.Text.Json 10.0.3
- System.Threading.Channels 10.0.3
- System.Threading.RateLimiting 8.0.0
.NET Framework 4.6.2+
- Microsoft.Bcl.Cryptography 8.0.0
- Microsoft.Bcl.TimeProvider 8.0.1
- Microsoft.Data.SqlClient.Extensions.Abstractions 7.1.0
- Microsoft.Data.SqlClient.Internal.Logging 7.1.0
- Microsoft.Data.SqlClient.SNI 7.1.0
- Microsoft.Extensions.Caching.Memory 8.0.1
- Microsoft.IdentityModel.JsonWebTokens 8.16.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 8.16.0
- System.Buffers 4.6.1
- System.Data.Common 4.3.0
- System.Diagnostics.DiagnosticSource 10.0.3
- System.Memory 4.6.3
- System.Runtime.InteropServices.RuntimeInformation 4.3.0
- System.Security.Cryptography.Pkcs 8.0.1
- System.Text.Json 10.0.3
- System.Threading.Channels 10.0.3
- System.Threading.RateLimiting 8.0.0
- System.ValueTuple 4.6.2