This update brings the below changes over the previous preview release:
- Added support for column encryption key caching when the server supports retrying queries that require enclave computations #1062
- Added support for configurable retry logic configuration file in .NET Standard #1090
- Updated
Microsoft.Data.SqlClient.SNI
(.NET Framework dependency) andMicrosoft.Data.SqlClient.SNI.runtime
(.NET Core/Standard dependency) version tov3.0.0
#1102 - Improved event counter display information #1091
- Modified column encryption key store provider registrations to give built-in system providers precedence over providers registered on connection and command instances. #1101
All changes in Microsoft.Data.SqlClient v3.0 over v2.1:
- Added support for Configurable Retry Logic #693 #966 Read more
- Added support for Event counters in .NET Core 3.1+ and .NET Standard 2.1+ #719 Read more
- Added support for Assembly Context Unloading in .NET Core #913
- Added missing
System.Runtime.Caching
dependency for .NET Standard assemblies #877 - Microsoft.Data.SqlClient now depends on Azure.Identity library to acquire a token for "Active Directory Managed Identity/MSI" and "Active Directory Service Principal" authentication modes. #1010 Read more
- Upgraded Native SNI dependency to v3.0.0-preview1 along with enhanced event tracing support #1006 Read more
- Added support for "Active Directory Default" authentication mode #1043 Read more
- Added support for connection-level and command-level registration of custom key store providers to enable multi-tenant applications to control key store access #1045 #1056 #1078 Read more
- Added IP address preference support for TCP connections #1015 Read more
- Fixed wrong results issues by changing the timeout timer to ensure a correct execution state #906
- Fixed Kerberos authentication issues when configured Server Principal Name (SPN) didn't contain default port #930
- Fixed MARS header errors when
MakeReadAsyncBlocking
App Context switch is set tofalse
#910 #922 - Fixed unwanted exceptions being thrown from
SqlDataReader.Dispose
#920 - Fixed issues connecting to SQL Server instance with instance name specified from Unix environment #870
- Fixed TCP Keep Alive issues in .NET Core #854
- Fixed Kerberos Authentication issues caused due to regression #845
- Fixed issues with System-Assigned Managed Identity in Azure Functions #829
- Fixed missing error messages in Managed SNI #882
- Fixed event source trace string issue #940
- Fixed wrong data blended with transactions in .NET Core by marking a connection as doomed if the transaction completes or aborts while there is an open result set #1023
- Fixed derived parameters containing incorrect typename #1020
- Fixed server connection leak possibilities when an exception occurs in pooling layer #890
- Fixed IP connection resolving logic in .NET Core #1016 #1031
- Fixed corrupted connection issue when an exception occurs during RPC execution with TVP types #1068
- Fixed race condition issues between SinglePhaseCommit and TransactionEnded events #1042
- Changed App Context switch
MakeReadAsyncBlocking
default tofalse
#937 - Replaced usage of
BinaryFormatter
withDataContractSerializer
#869 - Prohibited
DtdProcessing
onXmlTextReader
instance in .NET Core #884 - Improved performance by reducing memory allocations in
SerializeEncodingChar
/WriteEncodingChar
and some options boxing #785 - Improved performance by preventing orphaned active packets being GC'ed without clear #888
- Various performance improvements #889 #900
- Partial event source tracing improvements in .NET Core #867 #897
- Changes to share common files between NetFx and NetCore source code #827 #835 #838 #881
- Performance improvements in
SqlDateTime
toDateTime
internal conversion method #912 - Improved memory allocation by avoiding unnecessary context switching 1008
- Updated
Microsoft.Identity.Client
version from 4.21.1 to 4.22.0 #1036 - Various performance improvements #963 #996 #1004 #1012 #1017
- Event source tracing improvements #1018
- Changes to share common files between NetFx and NetCore source code #871 #887
- Updated error messages for enclave exceptions to include a link to a troubleshooting guide. #994
- Changes to share common files between projects #1022 #1038 #1040 #1033 #1028 #1039
- The minimum supported .NET Framework version has been increased to v4.6.1. .NET Framework v4.6.0 is no longer supported. #899
User Id
connection property now requiresClient Id
instead ofObject Id
for User-Assigned Managed Identity #1010 Read moreSqlDataReader
now returns aDBNull
value instead of an emptybyte[]
. Legacy behavior can be enabled by settingAppContext
switch Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior #998 Read more
This new feature introduces configurable support for client applications to retry on "transient" or "retriable" errors. Configuration can be done through code or app config files and retry operations can be applied to opening a connection or executing a command. This feature is disabled by default and is currently in preview. To enable this support, client applications must turn on the following safety switch:
AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.EnableRetryLogic", true);
Once the .NET AppContext switch is enabled, a retry logic policy can be defined for SqlConnection
and SqlCommand
independently, or together using various customization options.
New public APIs are introduced in SqlConnection
and SqlCommand
for registering a custom SqlRetryLogicBaseProvider
implementation:
public SqlConnection
{
public SqlRetryLogicBaseProvider RetryLogicProvider;
}
public SqlCommand
{
public SqlRetryLogicBaseProvider RetryLogicProvider;
}
API Usage examples can be found here:
Sample for retry logic options
New configuration sections have also been introduced to do the same registration from configuration files, without having to modify existing code:
<section name="SqlConfigurableRetryLogicConnection"
type="Microsoft.Data.SqlClient.SqlConfigurableRetryConnectionSection, Microsoft.Data.SqlClient"/>
<section name="SqlConfigurableRetryLogicCommand"
type="Microsoft.Data.SqlClient.SqlConfigurableRetryCommandSection, Microsoft.Data.SqlClient"/>
A simple example of using the new configuration sections in configuration files is below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="SqlConfigurableRetryLogicConnection"
type="Microsoft.Data.SqlClient.SqlConfigurableRetryConnectionSection, Microsoft.Data.SqlClient"/>
<section name="SqlConfigurableRetryLogicCommand"
type="Microsoft.Data.SqlClient.SqlConfigurableRetryCommandSection, Microsoft.Data.SqlClient"/>
<section name="AppContextSwitchOverrides"
type="Microsoft.Data.SqlClient.AppContextSwitchOverridesSection, Microsoft.Data.SqlClient"/>
</configSections>
<!--Enable safety switch in .NET Core-->
<AppContextSwitchOverrides value="Switch.Microsoft.Data.SqlClient.EnableRetryLogic=true"/>
<!--Retry method for SqlConnection-->
<SqlConfigurableRetryLogicConnection retryMethod ="CreateFixedRetryProvider" numberOfTries ="3" deltaTime ="00:00:10" maxTime ="00:00:30"
transientErrors="40615" />
<!--Retry method for SqlCommand containing SELECT queries-->
<SqlConfigurableRetryLogicCommand retryMethod ="CreateIncrementalRetryProvider" numberOfTries ="5" deltaTime ="00:00:10" maxTime ="00:01:10"
authorizedSqlCondition="\b(SELECT)\b" transientErrors="102, 4060, 0"/>
</configuration>
Alternatively, applications can implement their own provider of the SqlRetryLogicBaseProvider
base class, and register it with SqlConnection
/SqlCommand
.
The following counters are now available for applications targeting .NET Core 3.1+ and .NET Standard 2.1+:
Name | Display name | Description |
---|---|---|
active-hard-connections | Actual active connections currently made to servers | The number of connections that are currently open to database servers. |
hard-connects | Actual connection rate to servers | The number of connections per second that are being opened to database servers. |
hard-disconnects | Actual disconnection rate from servers | The number of disconnects per second that are being made to database servers. |
active-soft-connects | Active connections retrieved from the connection pool | The number of already-open connections being consumed from the connection pool. |
soft-connects | Rate of connections retrieved from the connection pool | The number of connections per second that are being consumed from the connection pool. |
soft-disconnects | Rate of connections returned to the connection pool | The number of connections per second that are being returned to the connection pool. |
number-of-non-pooled-connections | Number of connections not using connection pooling | The number of active connections that aren't pooled. |
number-of-pooled-connections | Number of connections managed by the connection pool | The number of active connections that are being managed by the connection pooling infrastructure. |
number-of-active-connection-pool-groups | Number of active unique connection strings | The number of unique connection pool groups that are active. This counter is controlled by the number of unique connection strings that are found in the AppDomain. |
number-of-inactive-connection-pool-groups | Number of unique connection strings waiting for pruning | The number of unique connection pool groups that are marked for pruning. This counter is controlled by the number of unique connection strings that are found in the AppDomain. |
number-of-active-connection-pools | Number of active connection pools | The total number of connection pools. |
number-of-inactive-connection-pools | Number of inactive connection pools | The number of inactive connection pools that haven't had any recent activity and are waiting to be disposed. |
number-of-active-connections | Number of active connections | The number of active connections that are currently in use. |
number-of-free-connections | Number of ready connections in the connection pool | The number of open connections available for use in the connection pools. |
number-of-stasis-connections | Number of connections currently waiting to be ready | The number of connections currently awaiting completion of an action and which are unavailable for use by the application. |
number-of-reclaimed-connections | Number of reclaimed connections from GC | The number of connections that have been reclaimed through garbage collection where Close or Dispose wasn't called by the application. Note Not explicitly closing or disposing connections hurts performance. |
These counters can be used with .NET Core global CLI tools: dotnet-counters
and dotnet-trace
in Windows or Linux and PerfView in Windows, using Microsoft.Data.SqlClient.EventSource
as the provider name. For more information, see Retrieve event counter values.
dotnet-counters monitor Microsoft.Data.SqlClient.EventSource -p
PerfView /onlyProviders=*Microsoft.Data.SqlClient.EventSource:EventCounterIntervalSec=1 collect
Microsoft.Data.SqlClient now depends on the Azure.Identity library to acquire tokens for "Active Directory Managed Identity/MSI" and "Active Directory Service Principal" authentication modes. This change brings the following changes to the public surface area:
- Breaking Change
The "User Id" connection property now requires "Client Id" instead of "Object Id" for "User-Assigned Managed Identity". - Public API
New read-only public property:SqlAuthenticationParameters.ConnectionTimeout
- Dependency
Azure.Identity v1.3.0
Microsoft.Data.SqlClient.SNI
(.NET Framework dependency) and Microsoft.Data.SqlClient.SNI.runtime
(.NET Core/Standard dependency) versions have been updated to v3.0.0-preview1.21104.2
. Event tracing in SNI.dll will no longer be enabled through a client application. Subscribing a session to the Microsoft.Data.SqlClient.EventSource provider through tools like xperf or perfview will be sufficient. For more information, see Event tracing support in Native SNI.
SqlDataReader
returns a DBNull
value instead of an empty byte[]
. To enable the legacy behavior, you must enable the following AppContext switch on application startup:
"Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior"
This PR introduces a new SQL Authentication method, Active Directory Default. This authentication mode widens the possibilities of user authentication, extending login solutions to the client environment, Visual Studio Code, Visual Studio, Azure CLI etc.
With this authentication mode, the driver acquires a token by passing "DefaultAzureCredential" from the Azure Identity library to acquire an access token. This mode attempts to use these credential types to acquire an access token in the following order:
- EnvironmentCredential
- Enables authentication to Azure Active Directory using client and secret, or username and password, details configured in the following environment variables: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_CLIENT_CERTIFICATE_PATH, AZURE_USERNAME, AZURE_PASSWORD (More details)
- ManagedIdentityCredential
- Attempts authentication to Azure Active Directory using a managed identity that has been assigned to the deployment environment. "Client Id" of "User Assigned Managed Identity" is read from the "User Id" connection property.
- SharedTokenCacheCredential
- Authenticates using tokens in the local cache shared between Microsoft applications.
- VisualStudioCredential
- Enables authentication to Azure Active Directory using data from Visual Studio
- VisualStudioCodeCredential
- Enables authentication to Azure Active Directory using data from Visual Studio Code.
- AzureCliCredential
- Enables authentication to Azure Active Directory using Azure CLI to obtain an access token.
InteractiveBrowserCredential is disabled in the driver implementation of "Active Directory Default", and "Active Directory Interactive" is the only option available to acquire a token using MFA/Interactive authentication.*
Further customization options are not available at the moment.
Microsoft.Data.SqlClient now offers more control of where master key store providers are accessible in an application in order to better support multi-tenant applications and their use of column encryption/decryption. The following APIs are introduced to allow registration of custom master key store providers on instances of SqlConnection
and SqlCommand
:
public class SqlConnection
{
public void RegisterColumnEncryptionKeyStoreProvidersOnConnection(IDictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders)
}
public class SqlCommand
{
public void RegisterColumnEncryptionKeyStoreProvidersOnCommand(IDictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders)
}
The static API on SqlConnection
, i.e. SqlConnection.RegisterColumnEncryptionKeyStoreProviders
to register custom master key store providers globally continues to be supported. The column encryption key cache maintained globally only applies to globally registered providers.
The built-in column master key store providers that are available for the Windows Certificate Store, CNG Store and CSP are pre-registered. No providers should be registered on the connection or command instances if one of the built-in column master key store providers is needed.
Custom master key store providers can be registered with the driver at three different layers. The global level is as it currently is. The new per-connection and per-command level registrations will be empty initially and can be set more than once.
The precedence of the three registrations are as follows:
- The per-command registration will be checked if it is not empty.
- If the per-command registration is empty, the per-connection registration will be checked if it is not empty.
- If the per-connection registration is empty, the global registration will be checked.
Once any key store provider is found at a registration level, the driver will NOT fall back to the other registrations to search for a provider. If providers are registered but the proper provider is not found at a level, an exception will be thrown containing only the registered providers in the registration that was checked.
The column encryption keys (CEKs) for custom key store providers registered using the new instance-level APIs will not be cached by the driver. The key store providers need to implement their own cache to gain performance. This local cache of column encryption keys implemented by custom key store providers will be disabled by the driver if the key store provider instance is registered in the driver at the global level.
A new API has also been introduced on the SqlColumnEncryptionKeyStoreProvider
base class to set the cache time to live:
public abstract class SqlColumnEncryptionKeyStoreProvider
{
// The default value of Column Encryption Key Cache Time to Live is 0.
// Provider's local cache is disabled for globally registered providers.
// Custom key store provider implementation must include column encryption key cache to provide caching support to locally registered providers.
public virtual TimeSpan? ColumnEncryptionKeyCacheTtl { get; set; } = new TimeSpan(0);
}
A new connection property IPAddressPreference
is introduced to specify the IP address family preference to the driver when establishing TCP connections. If Transparent Network IP Resolution
(in .NET Framework) or Multi Subnet Failover
is set to true
, this setting has no effect. Below are the three accepted values for this property:
-
IPv4First
- This is the default preference value. The driver will use resolved IPv4 addresses first. If none of them can be connected to successfully, it will try resolved IPv6 addresses.
-
IPv6First
- The driver will use resolved IPv6 addresses first. If none of them can be connected to successfully, it will try resolved IPv4 addresses.
-
UsePlatformDefault
- The driver will try IP addresses in the order received from the DNS resolution response.
- .NET Framework 4.6.1+ (Windows x86, Windows x64)
- .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
- Microsoft.Data.SqlClient.SNI 3.0.0
- Azure.Identity 1.3.0
- Microsoft.Identity.Client 4.14.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 5.6.0
- Microsoft.IdentityModel.JsonWebTokens 5.6.0
- System.Configuration.ConfigurationManager 4.7.0
- System.Text.Encodings.Web 4.7.2
- Microsoft.Data.SqlClient.SNI.runtime 3.0.0
- Microsoft.Win32.Registry 4.7.0
- System.Security.Principal.Windows 4.7.0
- System.Text.Encoding.CodePages 4.7.0
- System.Text.Encodings.Web 4.7.2
- System.Diagnostics.DiagnosticSource 4.7.0
- System.Configuration.ConfigurationManager 4.7.0
- System.Runtime.Caching 4.7.0
- Azure.Identity 1.3.0
- Microsoft.Identity.Client 4.14.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 5.6.0
- Microsoft.IdentityModel.JsonWebTokens 5.6.0
- Microsoft.Data.SqlClient.SNI.runtime 3.0.0
- Microsoft.Win32.Registry 4.7.0
- System.Security.Principal.Windows 4.7.0
- System.Text.Encoding.CodePages 4.7.0
- System.Text.Encodings.Web 4.7.2
- System.Diagnostics.DiagnosticSource 4.7.0
- System.Configuration.ConfigurationManager 4.7.0
- System.Runtime.Caching 4.7.0
- Azure.Identity 1.3.0
- Microsoft.Identity.Client 4.14.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 5.6.0
- Microsoft.IdentityModel.JsonWebTokens 5.6.0
- Microsoft.Data.SqlClient.SNI.runtime 3.0.0
- Microsoft.Win32.Registry 4.7.0
- System.Buffers 4.5.1
- System.Memory 4.5.4
- System.Security.Principal.Windows 4.7.0
- System.Text.Encoding.CodePages 4.7.0
- System.Text.Encodings.Web 4.7.2
- System.Runtime.Caching 4.7.0
- Azure.Identity 1.3.0
- Microsoft.Identity.Client 4.14.0
- Microsoft.IdentityModel.Protocols.OpenIdConnect 5.6.0
- Microsoft.IdentityModel.JsonWebTokens 5.6.0
- System.Configuration.ConfigurationManager 4.7.0
- System.Runtime.Loader 4.3.0