Microsoft.Data.SqlClient 命名空间简介

下载 ADO.NET

Microsoft.Data.SqlClient 命名空间实质上是 System.Data.SqlClient 命名空间的新版本。 Microsoft.Data.SqlClient 通常与 System.Data.SqlClient 保持相同的 API 和后向兼容性。 对于大多数应用程序而言,从 System.Data.SqlClient 迁移到 Microsoft.Data.SqlClient 的过程非常简单。 添加对 Microsoft.Data.SqlClient 的 NuGet 依赖关系,然后将引用和 using 语句更新为 Microsoft.Data.SqlClient。

与 System.Data.SqlClient 相比,不太常用的 API 存在的几项差异可能会影响某些应用程序。 有关这些差异,请参阅这份有用的移植速查表

API 参考

可以在 .NET API 浏览器中查找 Microsoft.Data.SqlClient API 详细信息。

Microsoft.Data.SqlClient 5.2 发行说明

5.2 新增功能

  • .NET Standard 中添加了对 SqlDiagnosticListener 的支持。 #1931
  • SqlBulkCopy 添加了新属性 RowsCopied64#2004了解详细信息
  • SqlConnection 添加了新的 API AccessTokenCallBack#1260了解详细信息
  • 在 Windows 上 .NET 中,添加了对 SuperSocketNetLib 加密功能注册表选项的支持 #2047
  • 在 .NET 6+ 中,添加了对 SqlBatch 的支持 #1825#2223了解详细信息
  • 添加了工作负载标识身份验证支持 #2159#2264
  • 在 .NET 中添加了本地化支持 #2210
  • 添加了对格鲁吉亚文排序规则的支持 #2194
  • 添加了对 Big Endian 系统的支持 #2170
  • 添加了对 .NET 8 的支持 #2230
  • 针对 System.Runtime.Caching 8.0.0、System.Configuration.ConfigurationManager 8.0.0 及 System.Diagnostics.DiagnosticSource 8.0.0 的主要 .NET 版本依赖项,添加了显式版本 #2303
  • 添加了在单独的包文件中生成调试符号的功能 #2137

向 SqlBulkCopy 添加了新属性 RowsCopied64

SqlBulkCopy 具有支持 long 值类型的新属性 RowsCopied64

请注意,现有 SqlBulkCopy.RowsCopied 行为保持不变。 该值超过 int.MaxValue 时,RowsCopied 可以返回一个负数。

示例用法:

    using (SqlConnection srcConn = new SqlConnection(srcConstr))
    using (SqlCommand srcCmd = new SqlCommand("select top 5 * from employees", srcConn))
    {
        srcConn.Open();
        using (DbDataReader reader = srcCmd.ExecuteReader())
        {
            using (SqlBulkCopy bulkcopy = new SqlBulkCopy(dstConn))
            {
                bulkcopy.DestinationTableName = dstTable;
                SqlBulkCopyColumnMappingCollection ColumnMappings = bulkcopy.ColumnMappings;

                ColumnMappings.Add("EmployeeID", "col1");
                ColumnMappings.Add("LastName", "col2");
                ColumnMappings.Add("FirstName", "col3");

                bulkcopy.WriteToServer(reader);
                long rowsCopied = bulkcopy.RowsCopied64;
            }
        }
    }

向 SqlConnection 添加了新属性 AccessTokenCallBack

SqlConnection 通过引入新的 TokenCredential 属性作为 AccessTokenCallBack 委托来返回联合身份验证访问令牌,从而支持 Func<SqlAuthenticationParameters, CancellationToken,Task<SqlAuthenticationToken>> 身份验证。

示例用法:

    using Microsoft.Data.SqlClient;
    using Azure.Identity;

    const string defaultScopeSuffix = "/.default";
    string connectionString = GetConnectionString();
    using SqlConnection connection = new SqlConnection(connectionString);
    
    connection.AccessTokenCallback = async (authParams, cancellationToken) =>
    {
        var cred = new DefaultAzureCredential();
        string scope = authParams.Resource.EndsWith(defaultScopeSuffix) ? authParams.Resource : authParams.Resource + defaultScopeSuffix;
        AccessToken token = await cred.GetTokenAsync(new TokenRequestContext(new[] { scope }), cancellationToken);
        return new SqlAuthenticationToken(token.Token, token.ExpiresOn);
    }
    
    connection.Open();
    Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
    Console.WriteLine("State: {0}", connection.State);

SqlBatch API

示例用法:

using Microsoft.Data.SqlClient;

class Program
{
    static void Main()
    {
        string str = "Data Source=(local);Initial Catalog=Northwind;"
        + "Integrated Security=SSPI;Encrypt=False";
        RunBatch(str);
    }

    static void RunBatch(string connString)
    {
        using var connection = new SqlConnection(connString);
        connection.Open();

        var batch = new SqlBatch(connection);

        const int count = 10;
        const string parameterName = "parameter";
        for (int i = 0; i < count; i++)
        {
            var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value");
            batchCommand.Parameters.Add(new SqlParameter(parameterName, i));
            batch.BatchCommands.Add(batchCommand);
        }

        // Optionally Prepare
        batch.Prepare();

        var results = new List<int>(count);
        using (SqlDataReader reader = batch.ExecuteReader())
        {
            do
            {
                while (reader.Read())
                {
                    results.Add(reader.GetFieldValue<int>(0));
                }
            } while (reader.NextResult());
        }
        Console.WriteLine(string.Join(", ", results));
    }
}

5.2 目标平台支持

  • .NET Framework 4.6.2+(Windows x86、Windows x64)
  • .NET 6.0+(Windows x86、Windows x64、Windows ARM64、Windows ARM、Linux、macOS)
  • .NET Standard 2.0+(Windows x86、Windows x64、Windows ARM64、Windows ARM、Linux、macOS)

GitHub 存储库中提供了完整的发行说明(包括依赖项):5.2 发行说明

5.1 中的中断性变更

  • 删除了对 .NET Core 3.1 的支持。 #1704#1823

5.1 中的新功能

  • 添加了对 DateOnly 以及 TimeOnly 的值 SqlParameterGetFieldValue 的支持。 #1813
  • 添加了对 TLS 1.3 for .NET Core 和 SNI Native 的支持。 #1821
  • 添加了 Encrypt=MandatoryEncrypt=StrictServerCertificate 设置。 #1822了解详细信息
  • 在面向 .NET Framework 时添加了 Windows ARM64 支持。 #1828

服务器证书

ServerCertificate 连接设置的默认值为空字符串。 当 Encrypt 设置为 MandatoryStrict 时,可以使用 ServerCertificate 在文件系统上指定证书文件的路径,以与服务器的 TLS/SSL 证书匹配。 指定的证书必须是完全匹配才有效。 接受的证书格式为 PEMDERCER。 下面是用法示例:

"Data Source=...;Encrypt=Strict;ServerCertificate=C:\\certificates\\server.cer"

5.1 目标平台支持

  • .NET Framework 4.6.2+(Windows x86、Windows x64)
  • .NET 6.0+(Windows x86、Windows x64、Windows ARM64、Windows Azure 资源管理器、Linux、macOS)
  • .NET Standard 2.0+(Windows x86、Windows x64、Windows ARM64、Windows ARM、Linux、macOS)

GitHub 存储库中提供了完整的发行说明(包括依赖项):5.1 发行说明

Microsoft.Data.SqlClient 5.0 发行说明

5.0 中的中断性变更

  • 删除了对 .NET Framework 4.6.1 的支持 #1574
  • 添加了对 Microsoft.SqlServer.Server 包的依赖项。 如果应用程序引用该命名空间并且仍然具有从 .NET Core 对 System.Data.SqlClient 的直接或间接包引用,则此新依赖项可能会导致命名空间冲突。
  • Microsoft.Data.SqlClient.Server 命名空间中删除了类,并将其替换为 Microsoft.SqlServer.Server 包中受支持的类型。#1585。 受影响的类和枚举包括:
    • Microsoft.Data.SqlClient.Server.IBinarySerialize -> Microsoft.SqlServer.Server.IBinarySerialize
    • Microsoft.Data.SqlClient.Server.InvalidUdtException -> Microsoft.SqlServer.Server.InvalidUdtException
    • Microsoft.Data.SqlClient.Server.SqlFacetAttribute -> Microsoft.SqlServer.Server.SqlFacetAttribute
    • Microsoft.Data.SqlClient.Server.SqlFunctionAttribute -> Microsoft.SqlServer.Server.SqlFunctionAttribute
    • Microsoft.Data.SqlClient.Server.SqlMethodAttribute -> Microsoft.SqlServer.Server.SqlMethodAttribute
    • Microsoft.Data.SqlClient.Server.SqlUserDefinedAggregateAttribute -> Microsoft.SqlServer.Server.SqlUserDefinedAggregateAttribute
    • Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute -> Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute
    • (枚举)Microsoft.Data.SqlClient.Server.DataAccessKind -> Microsoft.SqlServer.Server.DataAccessKind
    • (枚举)Microsoft.Data.SqlClient.Server.Format -> Microsoft.SqlServer.Server.Format
    • (枚举)Microsoft.Data.SqlClient.Server.SystemDataAccessKind -> Microsoft.SqlServer.Server.SystemDataAccessKind

5.0 中的新功能

  • 增加了对 TDS8 的支持。 要使用 TDS 8,用户应在连接字符串中指定 Encrypt=Strict。 #1608阅读更多
  • 添加了对在连接上指定服务器 SPN 和故障转移服务器 SPN 的支持。 #1607阅读更多
  • 在面向 Windows 上的 .NET Core 时添加了对别名的支持。 #1588阅读更多
  • 添加了 SqlDataSourceEnumerator。 #1430阅读更多
  • 添加了一个新的 AppContext 切换以抑制不安全的 TLS 警告。 #1457阅读更多

TDS 8 增强的安全性

要使用 TDS 8,请在连接字符串中指定 Encrypt=Strict。 严格模式禁用 TrustServerCertificate(在严格模式下始终被视为 False)。 添加了 HostNameInCertificate 以帮助某些严格模式方案。 TDS 8 在安全、加密的 TLS 连接中开始并继续所有服务器通信。

添加了新的加密值以阐明连接加密行为。 Encrypt=Mandatory 等效于 Encrypt=True 并在 TDS 连接协商过程中加密连接。 Encrypt=Optional 等效于 Encrypt=False,并且只有在服务器告诉客户端在 TDS 连接协商过程中需要加密时才会加密连接。

有关加密与服务器的连接的详细信息,请参阅加密和证书验证

当使用别名连接到具有加密功能的服务器(该服务器的服务器证书的名称或备用使用者名称与客户端用于标识服务器的名称不同,例如 DNS 别名)时,可以在连接字符串中指定 HostNameInCertificate。 用法示例:HostNameInCertificate=MyDnsAliasName

服务器 SPN

在具有唯一域/林拓扑的环境中进行连接时,可能对服务器 SPN 有特定要求。 ServerSPN/服务器 SPN 和 FailoverServerSPN/故障转移服务器 SPN 连接字符串设置可用于替代域环境中集成身份验证期间使用的自动生成的服务器 SPN

支持 SQL 别名

用户可以使用 SQL Server 配置管理器配置别名。 这些别名存储在 Windows 注册表中,并且在面向 .NET Framework 时已受支持。 此版本在面向 Windows 上的 .NET 或 .NET Core 时为别名提供支持。

SQL 数据源枚举器支持

提供了一种枚举本地网络内的所有可用 SQL Server 实例的机制。

using Microsoft.Data.Sql;
static void Main()  
  {  
    // Retrieve the enumerator instance and then the data.  
    SqlDataSourceEnumerator instance =  
      SqlDataSourceEnumerator.Instance;  
    System.Data.DataTable table = instance.GetDataSources();  
  
    // Display the contents of the table.  
    DisplayData(table);  
  
    Console.WriteLine("Press any key to continue.");  
    Console.ReadKey();  
  }  
  
  private static void DisplayData(System.Data.DataTable table)  
  {  
    foreach (System.Data.DataRow row in table.Rows)  
    {  
      foreach (System.Data.DataColumn col in table.Columns)  
      {  
        Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);  
      }  
      Console.WriteLine("============================");  
    }  
  }  

禁止显示不安全的 TLS 警告

如果使用低于 1.2 的 TLS 版本与服务器协商,则将在控制台上输出安全警告。 通过在应用程序启动时启用以下 AppContext 切换,可以在 Encrypt = false 时在 SQL 连接上抑制此警告:

Switch.Microsoft.Data.SqlClient.SuppressInsecureTLSWarning

5.0 目标平台支持

  • .NET Framework 4.6.2+(Windows x86、Windows x64)
  • .NET Core 3.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)

GitHub 存储库中提供了完整的发行说明(包括依赖项):5.0 发行说明

Microsoft.Data.SqlClient 4.1 发行说明

GitHub 存储库中提供了完整的发行说明(包括依赖项):4.1 发行说明

4\.1 中的新功能

引入证明协议 None

在连接字符串中允许使用名为 None 的新证明协议。 此协议允许用户放弃 VBS enclave 的 enclave 证明。 设置此协议后,enclave 证明 URL 属性为可选。

连接字符串示例:

//Attestation protocol NONE with no URL
"Data Source = {server}; Initial Catalog = {db}; Column Encryption Setting = Enabled; Attestation Protocol = None;"

4.1 目标平台支持

  • .NET Framework 4.6.1+(Windows x86、Windows x64)
  • .NET Core 3.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 4.0 发行说明

GitHub 存储库中提供了完整的发行说明(包括依赖项):4.0 发行说明

4\.0 中的中断性变更

  • 默认将 Encrypt 连接字符串属性更改为 true#1210了解详细信息
  • 驱动程序现在将引发 SqlException 替换 AggregateException 以用于 Active Directory 身份验证模式。 #1213
  • 从 .NET Framework 中删除了过时的 Asynchronous Processing 连接属性。 #1148
  • 删除了 Configurable Retry Logic 安全开关。 #1254了解详细信息
  • 删除了对 .NET Core 2.1 的支持 #1272
  • [.NET Framework] 如果在使用 Active Directory Integrated 身份验证时在连接字符串中提供了用户 ID,将不会引发异常 #1359

4\.0 中的新功能

加密默认值设置为 true

Encrypt 连接设置的默认值已从 false 更改为 true。 随着云数据库的使用越来越多,以及需要确保这些连接的安全,是时候进行这种向后兼容性的中断性变更了。

确保在需要加密时连接失败

在客户端加密库已禁用或不可用的情况下,当“加密”设置为 true 或服务器要求加密时,可能会建立未加密的连接。

用于使用系统默认协议的应用上下文切换

驱动程序不支持 TLS 1.3;因此,默认已从支持的协议列表中将其删除。 用户可以通过启用以下应用上下文开关,切换回强制使用操作系统的客户端协议:

Switch.Microsoft.Data.SqlClient.UseSystemDefaultSecureProtocols

启用优化参数绑定

Microsoft.Data.SqlClient 引入了一个新的 SqlCommand API,即 EnableOptimizedParameterBinding,用于提高具有大量参数的查询的性能。 默认情况下禁用此属性。 如果设置为 true,在执行命令时,参数名称不会被发送到 SQL Server 实例。

public class SqlCommand
{
    public bool EnableOptimizedParameterBinding { get; set; }
}

删除可配置的重试逻辑安全开关

使用可配置的重试逻辑功能时,不再需要应用上下文开关“Switch.Microsoft.Data.SqlClient.EnableRetryLogic”。 生产环境中现在支持该功能。 此功能的默认行为将继续为非重试策略,客户端应用程序需要替代该策略才能启用重试。

SqlLocalDb 共享实例支持

使用托管 SNI 时,现在支持 SqlLocalDb 共享实例。

  • 可能的场景:
    • (localdb)\.(连接到 SqlLocalDb 的默认实例)
    • (localdb)\<named instance>
    • (localdb)\.\<shared instance name>(*新添加的支持)

GetFieldValueAsync<T>GetFieldValue<T> 支持 XmlReaderTextReaderStream 类型

使用 GetFieldValueAsync<T>GetFieldValue<T> 时,现在支持 XmlReaderTextReaderStream 类型。

用法示例:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    using (SqlCommand command = new SqlCommand(query, connection))
    {
        connection.Open();
        using (SqlDataReader reader = await command.ExecuteReaderAsync())
        {
            if (await reader.ReadAsync())
            {
                using (Stream stream = await reader.GetFieldValueAsync<Stream>(1))
                {
                    // Continue to read from stream
                }
            }
        }
    }
}

4.0 目标平台支持

  • .NET Framework 4.6.1+(Windows x86、Windows x64)
  • .NET Core 3.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 3.0 发行说明

GitHub 存储库中提供了完整的发行说明(包括依赖项):3.0 发行说明

3\.0 中的中断性变更

  • 支持的最低 .NET Framework 版本已增加到 v4.6.1。 .NET Framework v4.6.0 不再受支持。 #899
  • 对于“用户分配的托管标识”,User Id 连接属性现在需要 Client Id 而不是 Object Id#1010了解详细信息
  • SqlDataReader 现在返回 DBNull 值而不是空的 byte[]。 可以通过设置 AppContext 开关 Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior 来启用旧版行为#998了解详细信息

3\.0 中的新增功能

可配置的重试逻辑

此新功能引入了对客户端应用程序的可配置支持,以重试“暂时性”或“可重试”错误。 可通过代码或应用配置文件完成配置,并可应用重试操作以打开连接或执行命令。 默认情况下,此功能是禁用的,目前提供预览版。 要启用此支持,客户端应用程序必须打开以下安全开关:

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

启用 .NET AppContext 开关后,可以单独为 SqlConnectionSqlCommand 定义重试逻辑策略,也可以使用各种自定义选项来一起定义它们。

SqlConnectionSqlCommand 中引入了新的公共 API,用于注册自定义 SqlRetryLogicBaseProvider 实现:

public SqlConnection
{
    public SqlRetryLogicBaseProvider RetryLogicProvider;
}

public SqlCommand
{
    public SqlRetryLogicBaseProvider RetryLogicProvider;
}

可在此处找到 API 用法示例:

using Microsoft.Data.SqlClient;

/// Detecting retriable exceptions is a vital part of the retry pattern.
/// Before applying retry logic it is important to investigate exceptions and choose a retry provider that best fits your scenario.
/// First, log your exceptions and find transient faults.
/// The purpose of this sample is to illustrate how to use this feature and the condition might not be realistic.
class RetryLogicSample
{
    private const string DefaultDB = "Northwind";
    private const string CnnStringFormat = "Server=localhost; Initial Catalog={0}; Integrated Security=true; pooling=false;";
    private const string DropDatabaseFormat = "DROP DATABASE {0}";

    // For general use
    private static SqlConnection s_generalConnection = new SqlConnection(string.Format(CnnStringFormat, DefaultDB));

    static void Main(string[] args)
    {
        // 1. Define the retry logic parameters
        var options = new SqlRetryLogicOption()
        {
            NumberOfTries = 5,
            MaxTimeInterval = TimeSpan.FromSeconds(20),
            DeltaTime = TimeSpan.FromSeconds(1)
        };

        // 2. Create a retry provider
        var provider = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options);

        // define the retrying event to report the execution attempts
        provider.Retrying += (object s, SqlRetryingEventArgs e) =>
            {
                int attempts = e.RetryCount + 1;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"attempt {attempts} - current delay time:{e.Delay} \n");
                Console.ForegroundColor = ConsoleColor.DarkGray;
                if (e.Exceptions[e.Exceptions.Count - 1] is SqlException ex)
                {
                    Console.WriteLine($"{ex.Number}-{ex.Message}\n");
                }
                else
                {
                    Console.WriteLine($"{e.Exceptions[e.Exceptions.Count - 1].Message}\n");
                }

                // It is not a good practice to do time-consuming tasks inside the retrying event which blocks the running task.
                // Use parallel programming patterns to mitigate it.
                if (e.RetryCount == provider.RetryLogic.NumberOfTries - 1)
                {
                    Console.WriteLine("This is the last chance to execute the command before throwing the exception.");
                    Console.WriteLine("Press Enter when you're ready:");
                    Console.ReadLine();
                    Console.WriteLine("continue ...");
                }
            };

        // Open the general connection.
        s_generalConnection.Open();

        try
        {
            // Assume the database is being created and other services are going to connect to it.
            RetryConnection(provider);
        }
        catch
        {
            // exception is thrown if connecting to the database isn't successful.
            throw;
        }
    }

    private static void ExecuteCommand(SqlConnection cn, string command)
    {
        using var cmd = cn.CreateCommand();
        cmd.CommandText = command;
        cmd.ExecuteNonQuery();
    }

    private static void RetryConnection(SqlRetryLogicBaseProvider provider)
    {
        // Change this if you already have a database with the same name in your database.
        string dbName = "Invalid_DB_Open";

        // Create a connection to an invalid database.
        using var cnn = new SqlConnection(string.Format(CnnStringFormat, dbName));
        // 3. Assign the `provider` to the connection
        cnn.RetryLogicProvider = provider;
        Console.WriteLine($"Connecting to the [{dbName}] ...");
        // Manually execute the following command in SSMS to create the invalid database while the SqlConnection is attempting to connect to it.
        // >> CREATE DATABASE Invalid_DB_Open;
        Console.WriteLine($"Manually, run the 'CREATE DATABASE {dbName};' in the SQL Server before exceeding the {provider.RetryLogic.NumberOfTries} attempts.");
        // the connection tries to connect to the database 5 times
        Console.WriteLine("The first attempt, before getting into the retry logic.");
        cnn.Open();
        Console.WriteLine($"Connected to the [{dbName}] successfully.");

        cnn.Close();

        // Drop it after test
        ExecuteCommand(s_generalConnection, string.Format(DropDatabaseFormat, dbName));
        Console.WriteLine($"The [{dbName}] is removed.");
    }
}
/// Detecting retriable exceptions is a vital part of the retry pattern.
/// Before applying retry logic it is important to investigate exceptions and choose a retry provider that best fits your scenario.
/// First, log your exceptions and find transient faults.
/// The purpose of this sample is to illustrate how to use this feature and the condition might not be realistic.

    private const string DefaultDB = "Northwind";
    private const string CnnStringFormat = "Server=localhost; Initial Catalog={0}; Integrated Security=true; pooling=false;";
    private const string DropDatabaseFormat = "DROP DATABASE {0}";
    private const string CreateDatabaseFormat = "CREATE DATABASE {0}";

    // For general use
    private static SqlConnection s_generalConnection = new SqlConnection(string.Format(CnnStringFormat, DefaultDB));

    static void Main(string[] args)
    {
        // 1. Define the retry logic parameters
        var options = new SqlRetryLogicOption()
        {
            NumberOfTries = 5,
            MaxTimeInterval = TimeSpan.FromSeconds(20),
            DeltaTime = TimeSpan.FromSeconds(1),
            AuthorizedSqlCondition = null,
            // error number 3702 : Cannot drop database "xxx" because it is currently in use.
            TransientErrors = new int[] {3702}
        };

        // 2. Create a retry provider
        var provider = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options);

        // define the retrying event to report execution attempts
        provider.Retrying += (object s, SqlRetryingEventArgs e) =>
            {
                int attempts = e.RetryCount + 1;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"attempt {attempts} - current delay time:{e.Delay} \n");
                Console.ForegroundColor = ConsoleColor.DarkGray;
                if (e.Exceptions[e.Exceptions.Count - 1] is SqlException ex)
                {
                    Console.WriteLine($"{ex.Number}-{ex.Message}\n");
                }
                else
                {
                    Console.WriteLine($"{e.Exceptions[e.Exceptions.Count - 1].Message}\n");
                }

                // It is not good practice to do time-consuming tasks inside the retrying event which blocks the running task.
                // Use parallel programming patterns to mitigate it.
                if (e.RetryCount == provider.RetryLogic.NumberOfTries - 1)
                {
                    Console.WriteLine("This is the last chance to execute the command before throwing the exception.");
                    Console.WriteLine("Press Enter when you're ready:");
                    Console.ReadLine();
                    Console.WriteLine("continue ...");
                }
            };

        // Open a general connection.
        s_generalConnection.Open();

        try
        {
            // Assume the database is creating and other services are going to connect to it.
            RetryCommand(provider);
        }
        catch
        {
            s_generalConnection.Close();
            // exception is thrown if connecting to the database isn't successful.
            throw;
        }
        s_generalConnection.Close();
    }

    private static void ExecuteCommand(SqlConnection cn, string command)
    {
        using var cmd = cn.CreateCommand();
        cmd.CommandText = command;
        cmd.ExecuteNonQuery();
    }

    private static void FindActiveSessions(SqlConnection cnn, string dbName)
    {
        using var cmd = cnn.CreateCommand();
        cmd.CommandText = "DECLARE @query NVARCHAR(max) = '';" + Environment.NewLine +
            $"SELECT @query = @query + 'KILL ' + CAST(spid as varchar(50)) + ';' FROM sys.sysprocesses WHERE dbid = DB_ID('{dbName}')" + Environment.NewLine +
            "SELECT @query AS Active_sessions;";
        var reader = cmd.ExecuteReader();
        if (reader.Read())
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write($">> Execute the '{reader.GetString(0)}' command in SQL Server to unblock the running task.");
            Console.ResetColor();
        }
        reader.Close();
    }
var RetryLogicOption = new SqlRetryLogicOption()
{
    NumberOfTries = 5,
    // Declare the error number 102 as a transient error to apply the retry logic when it occurs.
    TransientErrors = new int[] { 102 },
    // When a SqlCommand executes out of a transaction, 
    // the retry logic will apply if it contains a 'select' keyword.
    AuthorizedSqlCondition = x => string.IsNullOrEmpty(x)
            || Regex.IsMatch(x, @"\b(SELECT)\b", RegexOptions.IgnoreCase),
    DeltaTime = TimeSpan.FromSeconds(1),
    MaxTimeInterval = TimeSpan.FromSeconds(60),
    MinTimeInterval = TimeSpan.FromSeconds(3)
};

此外,还引入了新的配置部分,以从配置文件进行相同的注册,而无需修改现有代码:

<section name="SqlConfigurableRetryLogicConnection"
            type="Microsoft.Data.SqlClient.SqlConfigurableRetryConnectionSection, Microsoft.Data.SqlClient"/>

<section name="SqlConfigurableRetryLogicCommand"
            type="Microsoft.Data.SqlClient.SqlConfigurableRetryCommandSection, Microsoft.Data.SqlClient"/>

以下是在配置文件中使用新配置部分的简单示例:

<?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>

或者,应用程序也可以实现自己的 SqlRetryLogicBaseProvider 基类提供程序,并使用 SqlConnection/SqlCommand 进行注册。

事件计数器

以下计数器现可用于面向 .NET Core 3.1+ 和 .NET Standard 2.1+ 的应用程序:

“属性” Display name 说明
active-hard-connections 当前与服务器建立的实际活动连接数 当前对数据库服务器开放的连接数。
hard-connects 与服务器的实际连接率 每秒向数据库服务器开放的连接数。
hard-disconnects 与服务器的实际断开连接率 每秒与数据库服务器断开连接的数量。
active-soft-connects 从连接池中检索的活动连接数 从连接池中使用的已开放连接数。
soft-connects 从连接池中检索的连接率 每秒从连接池使用的连接数。
soft-disconnects 返回到连接池的连接率 每秒返回到连接池的连接数。
number-of-non-pooled-connections 未使用连接池的连接数 未存入池中的活动连接的数量。
number-of-pooled-connections 连接池管理的连接数 活动连接管理连接池基础结构的数量。
number-of-active-connection-pool-groups 活动的唯一连接字符串数 活动的唯一连接池组数。 此计数器基于 AppDomain 中唯一连接字符串的数量。
number-of-inactive-connection-pool-groups 等待删除的唯一连接字符串数 标记为删除的唯一连接池组的数量。 此计数器基于 AppDomain 中唯一连接字符串的数量。
number-of-active-connection-pools 活动连接池数 连接池的总数。
number-of-inactive-connection-pools 非活动连接池数 最近无任何活动且等待被释放的非活动连接池的数量。
number-of-active-connections 活动连接数 当前正在使用的活动连接数。
number-of-free-connections 连接池中的就绪连接数 连接池中可用的打开的连接数。
number-of-stasis-connections 当前正在等待就绪的连接数 当前正在等待操作完成且应用程序无法使用的连接数。
number-of-reclaimed-connections 从 GC 回收的连接数 已通过垃圾回收回收的连接数,其中应用程序未调用 CloseDispose。 注意:不显式关闭或处理连接会影响性能。

这些计数器可与 .NET Core 全局 CLI 工具一起使用:Windows 或 Linux 中的 dotnet-countersdotnet-trace 以及 Windows 中的 PerfView,使用 Microsoft.Data.SqlClient.EventSource 作为提供程序名称。 有关详细信息,请参阅检索事件计数器值

dotnet-counters monitor Microsoft.Data.SqlClient.EventSource -p
PerfView /onlyProviders=*Microsoft.Data.SqlClient.EventSource:EventCounterIntervalSec=1 collect

Azure 标识依赖项简介

Microsoft.Data.SqlClient 现在依赖于 Azure.Identity 库来获取“Active Directory 托管标识/MSI”和“Active Directory 服务主体”身份验证模式的令牌 。 此变更为公共外围应用带来了以下更改:

  • 中断性变更
    对于“用户分配的托管标识”,“User Id”连接属性现在需要“Client Id”而不是“Object Id”。
  • 公共 API
    新的只读公共属性:SqlAuthenticationParameters.ConnectionTimeout
  • 依赖项
    Azure.Identity v1.3.0

SNI.dll 中的事件跟踪改进

Microsoft.Data.SqlClient.SNI(.NET Framework 依赖项)和 Microsoft.Data.SqlClient.SNI.runtime(.NET Core/Standard 依赖项)版本已更新至 v3.0.0-preview1.21104.2。 SNI.dll 中的事件跟踪不再通过客户端应用程序启用。 通过 xperfperfview 等工具订阅与 Microsoft.Data.SqlClient.EventSource 提供程序的会话就足够了。 有关详细信息,请参阅 Native SNI 中的事件跟踪支持

启用行版本 null 行为

SqlDataReader 返回 DBNull 值而不是空的 byte[]。 要启用旧版行为,必须在应用程序启动时启用以下 AppContext 开关:“Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior”

Microsoft Entra 默认身份验证支持以下身份验证方法:

注意

虽然 Microsoft Entra ID 是 Azure Active Directory (Azure AD) 的新名称,但为了防止中断现有环境,Azure AD 仍保留在一些硬编码的元素中,例如 UI 字段、连接提供程序、错误代码和 cmdlet。 在本文中,这两个名称可以互换。

此 PR 引入了新的 SQL 身份验证方法“Active Directory 默认”。 此身份验证模式可扩大 Microsoft Entra ID 用户身份验证的可能性,将登录解决方案扩展到客户端环境、Visual Studio Code、Visual Studio、Azure CLI 等。

在此身份验证模式下,驱动程序通过从 Azure 标识库传递“DefaultAzureCredential”来获取令牌和访问令牌。 此模式尝试使用这些凭据类型按以下顺序获取访问令牌:

  • EnvironmentCredential
    • 使用客户端和机密、用户名和密码、以下环境变量中配置的详细信息来启用 Microsoft Entra ID 身份验证:AZURE_TENANT_ID、AZURE_CLIENT_ID、AZURE_CLIENT_SECRET、AZURE_CLIENT_CERTIFICATE_PATH、AZURE_USERNAME、AZURE_PASSWORD(更多详细信息
  • ManagedIdentityCredential
    • 使用已分配给部署环境的托管标识尝试进行 Microsoft Entra ID 身份验证。 从“User Id”连接属性读取“用户分配的托管标识”的“客户端 ID”。
  • SharedTokenCacheCredential
    • 使用在 Microsoft 应用程序之间共享的本地缓存中的令牌进行身份验证。
  • VisualStudioCredential
    • 使用 Visual Studio 中的数据启用 Microsoft Entra ID 身份验证
  • VisualStudioCodeCredential
    • 使用 Visual Studio Code 中的数据启用 Microsoft Entra ID 身份验证。
  • AzureCliCredential
    • 使用 Azure CLI 获取访问令牌来启用 Microsoft Entra ID 身份验证。

InteractiveBrowserCredential 在“Active Directory 默认”的驱动程序实现中处于禁用状态,而“Active Directory 交互式”是唯一可用于通过 MFA/交互式身份验证获取令牌的选项。*

目前未提供其他自定义选项。

自定义主密钥存储提供程序注册增强功能

Microsoft.Data.SqlClient 现在可以更好地控制在应用程序中可访问主密钥存储提供程序的位置,以更好地支持多租户应用程序及其对列加密/解密的使用。 引入了以下 API 以允许在 SqlConnectionSqlCommand 实例上注册自定义主密钥存储提供程序:

public class SqlConnection
{
    public void RegisterColumnEncryptionKeyStoreProvidersOnConnection(IDictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders)
}
public class SqlCommand 
{
    public void RegisterColumnEncryptionKeyStoreProvidersOnCommand(IDictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders)
}

继续支持 SqlConnection 上的静态 API (SqlConnection.RegisterColumnEncryptionKeyStoreProviders) 全局注册自定义主密钥存储提供程序。 全局维护的列加密密钥缓存仅适用于全局注册的提供程序。

列主密钥存储提供程序注册优先级

可用于 Windows 证书存储、CNG 存储和 CSP 的内置列主密钥存储提供程序是预先注册的。 如果需要一种内置列主密钥存储提供程序,则不应在连接或命令实例上注册任何提供程序。

自定义主密钥存储提供程序可以在三个不同层的驱动程序中注册。 当前即为全局级别。 新的每个连接和每个命令级别的注册最初为空,且可多次设置。

三个注册的优先级如下:

  • 如果每个命令的注册不为空,则勾选该注册。
  • 如果每个命令的注册为空,且每个连接的注册不为空,则勾选每个连接的注册。
  • 如果每个连接的注册为空,则勾选全局注册。

在注册级别找到任何密钥存储提供程序后,驱动程序不会回退到其他注册来搜索提供程序。 如果提供程序已注册,但在某个级别找不到合适的提供程序,则会引发异常,即仅包含已勾选的注册中已注册的提供程序。

列加密密钥缓存优先级

驱动程序不会缓存使用新实例级别 API 注册的自定义密钥存储提供程序的列加密密钥 (CEK)。 密钥存储提供程序需要实现自己的缓存以提高性能。 如果密钥存储提供程序实例在驱动程序中的全局级别注册,则驱动程序将禁用由自定义密钥存储提供程序实现的列加密密钥的本地缓存。

SqlColumnEncryptionKeyStoreProvider 基类还引入了一个新的 API 来设置缓存生存时间:

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

IP 地址首选项

引入了新的连接属性 IPAddressPreference,以在建立 TCP 连接时指定驱动程序的 IP 地址系列首选项。 如果 Transparent Network IP Resolution(在 .NET Framework 中)或 Multi Subnet Failover 设置为 true,则此设置无效。 下面是此属性的三个可接受的值:

  • IPv4First

    • 此值为默认值。 驱动程序首先使用解析后的 IPv4 地址。 如果它们都无法成功连接,则将尝试使用解析后的 IPv6 地址。
  • IPv6First

    • 驱动程序首先使用解析后的 IPv6 地址。 如果它们都无法成功连接,则将尝试使用解析后的 IPv4 地址。
  • UsePlatformDefault

    • 驱动程序按照从 DNS 解析响应接收到的顺序尝试使用 IP 地址。

3.0 目标平台支持

  • .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 2.1 发行说明

GitHub 存储库中提供了完整的发行说明(包括依赖项):2.1 发行说明

2\.1 中的新增功能

对 Always Encrypted 的跨平台支持

Microsoft.Data.SqlClient v2.1 扩展了对以下平台的 Always Encrypted 支持:

支持 Always Encrypted 支持具有安全 Enclave 的 Always Encrypted 目标 Framework Microsoft.Data.SqlClient 版本 操作系统
.NET Framework 4.6 及更高版本 1.1.0+ Windows
.NET Core 2.1+ 2.1.0+1 Windows、Linux、macOS
2 .NET Standard 2.0 2.1.0+ Windows、Linux、macOS
.NET Standard 2.1+ 2.1.0+ Windows、Linux、macOS

注意

1 在 Microsoft.Data.SqlClient 版本 v2.1 之前,Always Encrypted 仅在 Windows 上受支持。 2 具有安全 Enclave 的 Always Encrypted 在 .NET Standard 2.0 上不受支持。

Microsoft Entra 设备代码流身份验证

Microsoft.Data.SqlClient v2.1 支持使用 MSAL.NET 进行“设备代码流”身份验证。 参考文档:OAuth2.0 设备授权授权流

连接字符串示例:

Server=<server>.database.windows.net; Authentication=Active Directory Device Code Flow; Database=Northwind;Encrypt=True

以下 API 支持自定义设备代码流回调机制:

public class ActiveDirectoryAuthenticationProvider
{
    // For .NET Framework, .NET Core and .NET Standard targeted applications
    public void SetDeviceCodeFlowCallback(Func<DeviceCodeResult, Task> deviceCodeFlowCallbackMethod)
}

Microsoft Entra 托管标识身份验证

Microsoft.Data.SqlClient v2.1 支持使用托管标识进行 Microsoft Entra ID 身份验证。

支持以下身份验证模式关键字:

  • Active Directory 托管标识
  • Active Directory MSI(用于跨 MS SQL 驱动程序兼容性)

连接字符串示例:

// For System Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory MSI; Encrypt=True; Initial Catalog={db};"

// For System Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory Managed Identity; Initial Catalog={db};"

// For User Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory MSI; Encrypt=True; User Id={ObjectIdOfManagedIdentity}; Initial Catalog={db};"

// For User Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory Managed Identity; Encrypt=True; User Id={ObjectIdOfManagedIdentity}; Initial Catalog={db};"

Microsoft Entra 交互式身份验证增强功能

Microsoft.Data.SqlClient v2.1 添加了以下 API,用于自定义“Microsoft Entra ID 交互式”身份验证体验:

public class ActiveDirectoryAuthenticationProvider
{
    // For .NET Framework targeted applications only
    public void SetIWin32WindowFunc(Func<IWin32Window> iWin32WindowFunc);

    // For .NET Standard targeted applications only
    public void SetParentActivityOrWindowFunc(Func<object> parentActivityOrWindowFunc);

    // For .NET Framework, .NET Core and .NET Standard targeted applications
    public void SetAcquireAuthorizationCodeAsyncCallback(Func<Uri, Uri, CancellationToken, Task<Uri>> acquireAuthorizationCodeAsyncCallback);

    // For .NET Framework, .NET Core and .NET Standard targeted applications
    public void ClearUserTokenCache();
}

SqlClientAuthenticationProviders 配置节

Microsoft.Data.SqlClient v2.1 引入了新的配置节 SqlClientAuthenticationProviders(现有 SqlAuthenticationProviders 的克隆)。 定义了适当的类型时,仍支持现有的配置节 SqlAuthenticationProviders,以实现向后兼容性。

新节允许应用程序配置文件同时包含 System.Data.SqlClient 的 SqlAuthenticationProviders 节和 Microsoft.Data.SqlClient 的 SqlClientAuthenticationProviders 节。

使用应用程序客户端 ID 进行 Microsoft Entra 身份验证。

Microsoft.Data.SqlClient v2.1 支持将用户定义的应用程序客户端 ID 传递到 Microsoft 身份验证库。 进行 Microsoft Entra ID 身份验证时,使用应用程序客户端 ID。

引入了以下新 API:

  1. ActiveDirectoryAuthenticationProvider 中引入了新的构造函数:
    [适用于所有 .NET 平台(.NET Framework、.NET Core 和 .NET Standard)]

    public ActiveDirectoryAuthenticationProvider(string applicationClientId)
    

    用法:

    string APP_CLIENT_ID = "<GUID>";
    SqlAuthenticationProvider customAuthProvider = new ActiveDirectoryAuthenticationProvider(APP_CLIENT_ID);
    SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, customAuthProvider);
    
    using (SqlConnection sqlConnection = new SqlConnection("<connection_string>")
    {
        sqlConnection.Open();
    }
    
  2. SqlAuthenticationProviderConfigurationSectionSqlClientAuthenticationProviderConfigurationSection 下引入了新的配置属性:
    [适用于 .NET Framework 和 .NET Core]

    internal class SqlAuthenticationProviderConfigurationSection : ConfigurationSection
    {
        ...
        [ConfigurationProperty("applicationClientId", IsRequired = false)]
        public string ApplicationClientId => this["applicationClientId"] as string;
    }
    
    // Inheritance
    internal class SqlClientAuthenticationProviderConfigurationSection : SqlAuthenticationProviderConfigurationSection
    { ... }
    

    用法:

    <configuration>
        <configSections>
            <section name="SqlClientAuthenticationProviders"
                             type="Microsoft.Data.SqlClient.SqlClientAuthenticationProviderConfigurationSection, Microsoft.Data.SqlClient" />
        </configSections>
        <SqlClientAuthenticationProviders applicationClientId ="<GUID>" />
    </configuration>
    
    <!--or-->
    
    <configuration>
        <configSections>
            <section name="SqlAuthenticationProviders"
                             type="Microsoft.Data.SqlClient.SqlAuthenticationProviderConfigurationSection, Microsoft.Data.SqlClient" />
        </configSections>
        <SqlAuthenticationProviders applicationClientId ="<GUID>" />
    </configuration>
    

数据分类 v2 支持

Microsoft.Data.SqlClient v2.1 引入了对数据分类的“敏感度级别”信息的支持。 现推出以下新 API:

public class SensitivityClassification
{
    public SensitivityRank SensitivityRank;
}

public class SensitivityProperty
{
    public SensitivityRank SensitivityRank;
}

public enum SensitivityRank
{
    NOT_DEFINED = -1,
    NONE = 0,
    LOW = 10,
    MEDIUM = 20,
    HIGH = 30,
    CRITICAL = 40
}

活动 SqlConnection 的服务器进程 ID

Microsoft.Data.SqlClient v2.1 为活动连接引入了新的 SqlConnection 属性 ServerProcessId

public class SqlConnection
{
    // Returns the server process Id (SPID) of the active connection.
    public int ServerProcessId;
}

本机 SNI 中的跟踪日志记录支持

Microsoft.Data.SqlClient v2.1 扩展了现有 SqlClientEventSource 实现,以支持 SNI.dll 中的事件跟踪。 必须使用类似于 Xperf 的工具捕获事件。

可以通过将命令发送到 SqlClientEventSource 来启用跟踪,如下图所示:

// Enables trace events:
EventSource.SendCommand(eventSource, (EventCommand)8192, null);

// Enables flow events:
EventSource.SendCommand(eventSource, (EventCommand)16384, null);

// Enables both trace and flow events:
EventSource.SendCommand(eventSource, (EventCommand)(8192 | 16384), null);

“命令超时”连接字符串属性

Microsoft.Data.SqlClient v2.1 引入了“命令超时”连接字符串属性来替代默认值 30 秒。 可以使用 SqlCommand 上的 CommandTimeout 属性来替代单个命令的超时。

连接字符串示例:

"Server={serverURL}; Initial Catalog={db}; Encrypt=True; Integrated Security=true; Command Timeout=60"

从本机 SNI 中删除符号

在 Microsoft.Data.SqlClient v2.1 中,我们从 Microsoft.Data.SqlClient.SNI.runtime NuGet(从 v2.1.1 开始)删除了 v2.0.0 中引入的符号。 公共符号现已发布到 Microsoft symbols Server,以供 BinSkim 等需要访问公共符号的工具使用。

Microsoft.Data.SqlClient 符号的源链接

从 Microsoft.Data.SqlClient v2.1 开始,Microsoft.Data.SqlClient 符号可源链接并发布到 Microsoft Symbols Server,以获得增强的调试体验,而无需下载源代码。

2.1 目标平台支持

  • .NET Framework 4.6+(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 2.0 发行说明

GitHub 存储库中提供了完整的发行说明(包括依赖项):2.0 发行说明

2\.0 中的重大更改

  • Enclave 提供程序接口 SqlColumnEncryptionEnclaveProvider 的访问修饰符已从 public 更改为 internal
  • SqlClientMetaDataCollectionNames 类中的常量已更新,以反映 SQL Server 中的更改。
  • 驱动程序现在在目标 SQL Server 强制执行 TLS 加密时执行服务器证书验证,这是 Azure 连接的默认设置。
  • SqlDataReader.GetSchemaTable() 现在返回空 DataTable,而不是 null
  • 驱动程序现执行十进制小数位舍入以匹配 SQL Server 行为。 为实现后向兼容性,可使用 AppContext 开关启用之前的截断行为。
  • 对于使用 Microsoft.Data.SqlClient 的 .NET Framework 应用程序,之前下载到 bin\x64bin\x86 文件夹的 SNI.dll 文件现命名为 Microsoft.Data.SqlClient.SNI.x64.dllMicrosoft.Data.SqlClient.SNI.x86.dll 并下载到 bin 目录。
  • SqlConnectionStringBuilder 获取连接字符串时,新的连接字符串属性同义词会替换旧的属性,以确保一致性。 阅读详细信息

2\.0 中的新增功能

Microsoft.Data.SqlClient 2.0 中引入了以下新功能。

DNS 故障复原

驱动程序现会将 IP 地址从每个成功连接缓存到支持该功能的 SQL Server 终结点。 如果在连接尝试期间发生 DNS 解析失败,驱动程序将尝试使用该服务器的已缓存 IP 地址(如存在)建立连接。

EventSource 跟踪

此版本引入了对捕获用于调试应用程序的事件跟踪日志的支持。 若要捕获这些事件,客户端应用程序必须侦听来自 SqlClient 的 EventSource 实现的事件:

Microsoft.Data.SqlClient.EventSource

有关详细信息,请参阅如何在 SqlClient 中启用事件跟踪

在 Windows 上启用托管网络

新的 AppContext 开关“Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows”支持在 Windows 上使用托管的 SNI 实现进行测试和调试。 此开关会切换驱动程序的行为,以便在 Windows 上的 .NET Core 2.1+ 和 .NET Standard 2.0+ 项目中使用托管的 SNI,从而消除对 Microsoft.Data.SqlClient 库的本机库的所有依赖项。

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

有关驱动程序中可用开关的完整列表,请参阅 SqlClient 中的 AppContext 开关

启用小数截断行为

默认情况下,驱动程序将舍入十进制数据小数位,这与 SQL Server 一样。 为实现后向兼容性,可将 AppContext 开关“Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal”设置为“true” 。

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

新的连接字符串属性同义词

已为以下现有的连接字符串属性添加了新的同义词,避免在包含多个字词的属性周围出现间距混淆。 为了向后兼容,仍支持旧属性名称。 但是,从 SqlConnectionStringBuilder 提取连接字符串时,现在会包含新的连接字符串属性。

现有的连接字符串属性 新的同义词
ApplicationIntent 应用程序意向
ConnectRetryCount 连接重试计数
ConnectRetryInterval 连接重试间隔
PoolBlockingPeriod 池阻塞期
MultipleActiveResultSets 多重活动结果集
MultiSubnetFailover 多重子网故障转移
TransparentNetworkIPResolution 透明网络 IP 解析
TrustServerCertificate 信任服务器证书

SqlBulkCopy RowsCopied 属性

RowsCopied 属性提供对已在正在进行的大容量复制操作中处理的行数的只读访问。 此值不一定等于添加到目标表中的最终行数。

连接打开替代

可替代 SqlConnection.Open() 的默认行为,以禁用由暂时性错误触发的 10 秒延迟和自动连接重试。

using SqlConnection sqlConnection = new SqlConnection("Data Source=(local);Integrated Security=true;Initial Catalog=AdventureWorks;");
sqlConnection.Open(SqlConnectionOverrides.OpenWithoutRetry);

注意

请注意,此替代只能应用于 SqlConnection.Open(),而不能应用于 SqlConnection.OpenAsync()。

对 Active Directory 交互模式的用户名支持

对 .NET Framework 和 .NET Core 使用 Microsoft Entra ID 交互身份验证模式时,可在连接字符串中指定用户名

使用“用户 ID”或“UID”连接字符串属性设置用户名 :

"Server=<server name>; Database=<db name>; Authentication=Active Directory Interactive; User Id=<username>;Encrypt=True;"

SqlBulkCopy 的排序提示

可提供排序提示,提高对具有聚集索引的表进行大容量复制操作的性能。 有关详细信息,请参阅大容量复制操作一节。

SNI 依赖项更改

Windows 上的 Microsoft.Data.SqlClient(.NET Core 和 .NET Standard)现依赖于 Microsoft.Data.SqlClient.SNI.runtime,取代了先前对 runtime.native.System.Data.SqlClient.SNI 的依赖 。 新的依赖项增加了对 ARM 平台以及 Windows 上已受支持的 ARM64、x64 和 x86 平台的支持。

2.0 目标平台支持

  • .NET Framework 4.6+(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 1.1.0 的发行说明

GitHub 存储库中提供了完整的发行说明(包括依赖项):1.1 发行说明

1\.1 中的新增功能

具有安全 Enclave 的 Always Encrypted

从 Microsoft SQL Server 2016 开始,提供 Always Encrypted。 从 Microsoft SQL Server 2019 开始,提供安全 enclave。 为使用 Enclave 功能,连接字符串应包括所需的证明协议和证明 URL。 例如:

"Attestation Protocol=HGS;Enclave Attestation Url=<attestation_url_for_HGS>"

有关详细信息,请参阅:

1.1 目标平台支持

  • .NET Framework 4.6+(Windows x86、Windows x64)
  • .NET Core 2.1+(Windows x86、Windows x64、Linux、macOS)
  • .NET Standard 2.0+(Windows x86、Windows x64、Linux、macOS)

Microsoft.Data.SqlClient 1.0 的发行说明

相较于现有 System.Data.SqlClient 命名空间,Microsoft.Data.SqlClient 命名空间的初始版本提供了更多的功能。

GitHub 存储库中提供了完整的发行说明(包括依赖项):1.0 发行说明

1\.0 中的新增功能

通过 .NET Framework 4.7.2 System.Data.SqlClient 提供的新增功能

  • 数据分类 - 在 Azure SQL 数据库和 Microsoft SQL Server 2019 中提供。

  • UTF-8 支持 - 在 Microsoft SQL Server 2019 中提供。

通过 .NET Core 2.2 System.Data.SqlClient 提供的新增功能

  • 数据分类 - 在 Azure SQL 数据库和 Microsoft SQL Server 2019 中提供。

  • UTF-8 支持 - 在 Microsoft SQL Server 2019 中提供。

  • 身份验证 - Active Directory 密码身份验证模式。

数据分类

当基础源支持该功能并包含有关数据敏感度和分类的元数据时,数据分类会引入一组新的 API,公开有关通过 SqlDataReader 检索到的对象的只读数据敏感度和分类信息。 有关示例应用程序,请参阅 SqlClient 中的数据发现和分类

public class SqlDataReader
{
    public Microsoft.Data.SqlClient.DataClassification.SensitivityClassification SensitivityClassification
}

namespace Microsoft.Data.SqlClient.DataClassification
{
    public class ColumnSensitivity
    {
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.SensitivityProperty> SensitivityProperties
    }
    public class InformationType
    {
        public string Id
        public string Name
    }
    public class Label
    {
        public string Id
        public string Name
    }
    public class SensitivityClassification
    {
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.ColumnSensitivity> ColumnSensitivities
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.InformationType> InformationTypes
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.Label> Labels
    }
    public class SensitivityProperty
    {
        public Microsoft.Data.SqlClient.DataClassification.InformationType InformationType
        public Microsoft.Data.SqlClient.DataClassification.Label Label
    }
}

UTF-8 支持

UTF-8 支持不需要更改任何应用程序代码。 当服务器支持 UTF-8 且基础列排序规则为 UTF-8 时,这些 SqlClient 更改会优化客户端与服务器之间的通信。 请参阅 SQL Server 2019 的新增功能中的 UTF-8 部分。

具有安全 enclave 的 Always Encrypted

通常,使用 .NET Framework 上的 System.Data.SqlClient 和内置列主密钥存储提供程序的现有文档现在还应与 .NET Core 一起使用。

配合使用 Always Encrypted 和 .NET Framework 数据提供程序进行开发

Always Encrypted:保护敏感数据并将加密密钥存储在 Windows 证书存储中

身份验证

可以使用“身份验证”连接字符串选项来指定不同的身份验证模式。 有关详细信息,请参阅 SqlAuthenticationMethod 的文档

注意

自定义密钥存储提供程序(如 Azure 密钥保管库提供程序)将需要更新以支持 Microsoft.Data.SqlClient。 同样,还需要更新 enclave 提供程序以支持 Microsoft.Data.SqlClient。 仅 .NET Framework 和 .NET Core 目标支持 Always Encrypted。 .NET Standard 不支持 Always Encrypted,因为 .NET Standard 缺少某些加密依赖项。

1.0 目标平台支持

  • .NET Framework 4.6+(Windows x86、Windows x64)
  • .NET Core 2.1+(Windows x86、Windows x64、Linux、macOS)
  • .NET Standard 2.0+(Windows x86、Windows x64、Linux、macOS)