用于 SQL Server 的 Microsoft.Data.SqlClient

下载 ADO.NET

Microsoft.Data.SqlClient 是适用于 SQL Server、Azure SQL 数据库、Azure SQL 托管实例、Azure Synapse Analytics、Microsoft Fabric 中的 SQL 数据库以及 Microsoft Fabric 中的 Warehouse 的受支持的 .NET 数据提供程序。 它以 NuGet 包的形式提供,独立于 .NET 运行时单独演进,并在新的开发项目中取代 System.Data.SqlClient。 它为 .NET 应用程序提供连接、命令、结果处理、事务、批量复制以及 SQL Server 特定功能。

选择起点

Azure SQL的生产基线

将此片段作为面向生产环境的 Azure SQL 数据访问路径的起点。 它从 IConfiguration 读取服务器和数据库名称,因此这些值来自主机配置的配置提供程序,如 appsettings.json、环境变量、Azure 应用程序配置 以及 密钥保管库 支持的设置。 该配置结合了以下特点:

  • 传输层安全(TLS)。
  • 托管标识。
  • 空闲连接弹性。
  • 通过可配置重试逻辑(CRL)实现初始连接重试,并支持结构化日志。
  • 对查询中途出现的瞬态错误进行命令级重试。
  • 故障转移组快速恢复。
  • 接受取消令牌的异步调用

为了提高安全性并支持跨环境配置,建议将连接信息保留在代码之外。 在生产环境中,将连接信息存储在应用的配置系统中,敏感值则使用 Azure 密钥保管库。 有关详细信息,请参阅 保护连接信息。

为简洁起见,本文中的 C# 代码片段省略了 using 指令和类包装。

该代码片段假设项目面向 .NET 8 或更高版本,并引用了 Microsoft.Data.SqlClient 和 Microsoft.Data.SqlClient.Extensions.Azure 7.1.1 包。 主机,如 .NET 通用主机或 ASP.NET Core,提供 ILogger 和 IConfiguration,配置则提供 Sql:Server 中的服务器名称和 Sql:Database 中的数据库名称。

public static async Task<string> QueryDatabaseNameAsync(
    IConfiguration config, ILogger logger, CancellationToken cancellationToken = default)
{
    string server = config["Sql:Server"]
        ?? throw new InvalidOperationException("Missing configuration value 'Sql:Server'.");
    string database = config["Sql:Database"]
        ?? throw new InvalidOperationException("Missing configuration value 'Sql:Database'.");

    var builder = new SqlConnectionStringBuilder
    {
        DataSource = server,
        InitialCatalog = database,
        Authentication = SqlAuthenticationMethod.ActiveDirectoryManagedIdentity,
        Encrypt = SqlConnectionEncryptOption.Strict, // TDS 8.0 encryption (server must support it)
        ConnectTimeout = 30,                         // per-attempt connect timeout in seconds
        // Retry transient failures during Open() and reconnect a dropped idle connection.
        // The configurable provider below adds another policy around Open().
        ConnectRetryCount = 3,
        ConnectRetryInterval = 10,
        MultiSubnetFailover = true,                  // recommended for TCP endpoints; enables parallel connect
        // ApplicationIntent = ApplicationIntent.ReadOnly, // uncomment to route to a readable secondary
    };

    // Add exponential backoff and jitter around Open().
    // TransientErrors is null, so the provider uses the driver's built-in transient error list.
    var openRetry = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(
        new SqlRetryLogicOption
        {
            NumberOfTries = 5,
            DeltaTime = TimeSpan.FromSeconds(3),
            MaxTimeInterval = TimeSpan.FromSeconds(60),
        });
    openRetry.Retrying += (_, args) =>
    {
        Exception last = args.Exceptions[^1];
        logger.LogWarning(
            last,
            "Retrying SQL connection to {Server}/{Database} (attempt {Attempt}) after {Delay}",
            server, database, args.RetryCount, args.Delay);
    };

    // Retry commands that hit deadlocks, lock timeouts, or common Azure SQL transient errors
    // mid-query on an established connection. Only attach this provider to commands whose
    // effect is safe to repeat.
    var commandRetry = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(
        new SqlRetryLogicOption
        {
            NumberOfTries = 4,
            DeltaTime = TimeSpan.FromSeconds(5),
            MaxTimeInterval = TimeSpan.FromSeconds(30),
            // Deadlock victim, lock-request timeout, and common Azure SQL transient errors.
            TransientErrors = new[] { 1205, 1222, 10928, 10929, 40197, 40501, 40613, 49918 },
        });
    commandRetry.Retrying += (_, args) =>
    {
        Exception last = args.Exceptions[^1];
        logger.LogWarning(
            last,
            "Retrying SQL command (attempt {Attempt}) after {Delay}",
            args.RetryCount, args.Delay);
    };

    await using var connection = new SqlConnection(builder.ConnectionString)
    {
        RetryLogicProvider = openRetry,
    };
    await connection.OpenAsync(cancellationToken);

    await using var command = new SqlCommand("SELECT DB_NAME()", connection)
    {
        RetryLogicProvider = commandRetry,
        CommandTimeout = 30,
    };

    var name = (string)await command.ExecuteScalarAsync(cancellationToken);
    logger.LogInformation("Connected to database {DatabaseName}", name);
    return name;
}

该方法返回它连接的数据库名称并记录 Connected to database <database>。 当重试发生时,它每次重试都会记录一条警告,并附带触发此次重试的异常信息。

片段的每个部分如何运作:

  • 目标:任何配置为 Microsoft Entra 认证的 SQL 数据库引擎 端点:Azure SQL 数据库、Azure SQL 托管实例、Microsoft Fabric 中的 SQL 数据库,以及 Azure 虚拟机 上或通过 Azure Arc 启用的 SQL Server 2022 及更高版本。
  • Encrypt = SqlConnectionEncryptOption.Strict选择TDS 8.0加密。 它需要SQL Server 2022及更高版本,Azure SQL 数据库、Azure SQL 托管实例,或Microsoft Fabric中的SQL数据库。 对于较旧的服务器,使用 SqlConnectionEncryptOption.Mandatory。
  • ActiveDirectoryManagedIdentity: 仅在有托管身份可用的情况下工作,如 Azure 应用服务、Azure Functions 或 Azure 虚拟机。 对于本地开发,请使用 SqlAuthenticationMethod.ActiveDirectoryDefault,它会尝试 Azure CLI、Visual Studio 登录和其他凭据来源。 不要将其用于生产环境,因为探测每个源会使连接变慢。 有关详细信息,请参见使用默认身份验证。
  • MultiSubnetFailover = true尝试并行连接所有解析得到的 IP 地址,并使用第一个成功的连接,避免了逐个 IP 的缓慢顺序尝试。 为 Azure SQL 数据库、Azure SQL 托管实例、Microsoft Fabric 中的 SQL 数据库、可用性组监听器和故障转移集群实例设置。 它对单IP目标是安全的。 它不支持命名实例、TCP以外的协议、拥有超过64个IP地址的实例,或者已被弃用的数据库镜像。 请使用 Always On 可用性组来替代其他解决方案。 更多信息请参见 高可用性与灾难恢复 以及 禁用透明网络IP解析。
  • ConnectRetryCount = 3 和 ConnectRetryInterval = 10:驱动程序会在 Open() 期间重试符合条件的暂时性故障,并在下一个命令中重新连接已断开的空闲连接。 默认计数是1。 三次间隔 10 秒的尝试可以撑过较长时间的重新配置或故障切换。 驱动程序只有在服务器名称以已知的 Azure SQL 域名结尾时才会将 1 提升到 2,例如 .database.windows.net,因此,自定义 DNS 别名会得到 1。
  • openRetry:分配给 SqlConnection.RetryLogicProvider,它在 Open() 周围增加了指数退避。 驱动程序在 ConnectTimeout 到期时停止其内部重试,因此在最坏情况下,在 OpenAsync 抛出异常之前会尝试五次,每次最长 30 秒,再加上退避时间。 每次空闲重新连接尝试也会执行完整 openRetry 策略,当该策略用尽重试时,空闲恢复就结束。
  • Serverless 自动暂停:对于 Azure SQL 数据库 serverless,请将 ConnectTimeout 调至至少 60 秒。 第一个 Open() 可能会在数据库恢复时因错误 40613 而失败,而 openRetry 会重试该操作。 客户端超时会以错误 -2出现,且不会重试,因此每次连接尝试都必须比恢复过程持续得更久。 更多信息请参见 自动暂停和自动恢复。
  • commandRetry:仅在重放命令安全时才将其附加到 SqlCommand.RetryLogicProvider:读取、由自然键保护的 MERGE、通过存储过程的 upserts 以及其他幂等操作。 它会跳过事务内的重试,因此应用代码必须重试多语句事务。 ExecuteReader 和 ExecuteScalar 仅重试在第一个结果集开始之前返回的错误。 ExecuteNonQuery 重新尝试整个调用。
  • 瞬态错误列表:设置 TransientErrors 会替换内置的错误列表。 要改为扩展它,请使用 SqlConfigurableRetryFactory.BaselineTransientErrors(Microsoft.Data.SqlClient 7.0 及更高版本)。
  • Retrying 事件: Retrying 每次重试前都会触发,包含重试计数、下一次延迟和目前的例外情况。 把它路由到 ILogger 或你的遥测管道。
  • 异常:该方法不捕捉异常。 已耗尽的提供程序会抛出 AggregateException,其中包含每次尝试产生的异常。 非瞬态错误作为原始异常传播。 调用方会将它和其余的请求上下文一并记录一次。
  • 取消:CancellationToken 会停止服务提供者在两次重试之间的等待。 在单次 Open 尝试中,它不会中断驱动程序的 ConnectRetryInterval 等待。 更多信息请参见 异步编程。
  • 提供程序生命周期:该代码片段在每次调用时创建重试提供程序,以保持自给自足。 在应用程序中,创建一次并重复使用它们。

有关此配置的每个部分的详细信息,请参阅:

学习核心数据访问任务

连接后,请按顺序使用以下文档:

  1. 执行命令以选择结果形状并运行 Transact-SQL(T-SQL)。
  2. 配置参数 以匹配数据库约定。
  3. 用 SqlDataReader 检索数据 ,处理行和多个结果。
  4. 使用存储过程修改数据 ,使其使用输出参数和返回值。
  5. 使用异步编程和取消 来添加调用方取消和有界超时。
  6. 在添加重试或生产诊断之前,先处理错误和消息。

主要功能

  • 现代 .NET 支持:运行在当前的 .NET 和 .NET 框架版本上。 关于各版本的详细分解,请参见 支持生命周期。
  • 默认加密:默认使用 Encrypt=true 的 TLS 加密连接。 为 TDS 8.0 加密设置 Encrypt=Strict。
  • Microsoft Entra ID 身份验证:通过托管标识、服务主体、交互、集成、默认凭据链和访问令牌流实现无密码连接。
  • Kerberos 和 NTLM:用于本地 Active Directory 和遗留场景的集成式 Windows 身份验证。
  • Always Encrypted:针对敏感列的客户端加密,并支持用于就地操作的可选安全隔离区。
  • 批量复制导入:使用 SqlBulkCopy 进行高吞吐量插入。
  • 连接池:默认开启。 一个可选择启用的 V2 池正处于评估阶段。
  • 连接弹性:内置连接重试(ConnectRetryCount 和 ConnectRetryInterval)以及可选择可配置的重试逻辑,用于连接和命令。
  • 丰富的SQL Server数据类型:datetimeoffset、、sql_variantJSON、向量、空间、XML和表值参数。
  • 诊断:事件源追踪、诊断计数器、提供者统计数据以及专门的故障排除指南。
  • 应用程序标识:设置 SqlConnection.RegisteredApplication,以向 SQL Server 标识您的库或工具(Microsoft.Data.SqlClient 7.1 及更高版本)。

开始

文章 Description
开始使用 SqlClient 驱动 搭建项目,创建数据库,连接、查询,并添加连接弹性。
安装、更新并部署 Microsoft。Data.SqlClient 安装NuGet包,选择一个版本,更新驱动,并准备部署输出。
支持生命周期 请查看支持的驱动版本和支持日期。
从 System.Data.SqlClient 迁移到 Microsoft。Data.SqlClient 更新包引用、命名空间、配置以及更改的驱动程序行为。
Microsoft。Data.Sql客户端命名空间与兼容性 了解 SqlClient 如何实现 ADO.NET,以及它与 System.Data.SqlClient、.NET 和 SQL Server 的兼容性。
Microsoft.Data.SqlClient 中的新增功能 查找当前版本、重大升级变更以及上游发布说明。

配置和连接

文章 Description
连接到数据源 打开和管理连接,并响应连接状态的变化。
连接字符串 配置服务器、数据库、认证、加密和连接行为。
加密和证书验证 配置加密连接和服务器证书验证。
SQL Server 连接池 高效地重复利用物理连接。
处理错误和消息 发现错误并接收信息信息。

认证与安全

文章 Description
Microsoft.Data.SqlClient 的安全最佳实践 请查看认证、授权和应用安全指南。
Microsoft Entra 身份验证 连接托管身份、服务主体、密码和交互流。
保护连接信息 不要把凭据和连接设置写进应用代码。
始终加密 保护敏感列值免受数据库系统影响。
具有安全隔区的 Always Encrypted 在加密数据上运行丰富的操作,并设置一个安全的隔离区。

检索和更新数据

文章 Description
执行命令 执行参数化的SQL语句和存储过程。
DataAdapter 和 DataReader 流式传输结果集,或填充断开连接的数据结构。
使用 SqlBatch 执行多个命令 发送一组有序的命令并处理它们的结果。
流数据 传输大型二进制、文本、XML 和 JSON 值时,无需缓冲完整值。
事务和并发性 使用本地和分布式事务以及并发控制。
检索数据库模式信息 探索模式集合和限制。
批量复制操作 借助 SqlBulkCopy 高效加载大型数据集。
表值参数 向参数化语句或存储过程发送多行数据。
多重活动结果集 (MARS) 在同一连接上交错执行多个批次。

数据类型

文章 Description
SQL Server 数据类型映射 将 SQL Server 类型映射到 .NET 和 System.Data.SqlTypes 类型。
JSON 数据 发送并检索 SQL Server json 数据类型。
向量数据 发送和检索向量值。
XML数据 读取、写入并参数化XML值。
二进制和大值数据 流式处理并更新二进制、FILESTREAM 和大值数据。

可靠性与诊断

文章 Description
可配置的重试逻辑 使用有边界的策略重试瞬态连接故障和命令故障。
高可用性和灾难恢复 连接可用性组侦听器和故障转移伙伴。
SqlClient 中的事件计数器 监控活跃连接、合并连接及其他驱动指标。
启用事件源追踪 详细记录驾驶事件以供诊断。
SqlClient 故障排除指南 诊断常见连接和驱动问题。
查询通知 查询结果变更时收到通知。

SQL Server功能

文章 Description
SQL Server 功能和 ADO.NET 浏览通过 SqlClient 提供的 SQL Server 专属功能。
本地数据库 连接到 SQL Server Express LocalDB 实例。
数据发现和分类 从结果集中读取敏感性分类元数据。

参考和资源

文章 Description
Microsoft.Data.SqlClient API 参考 浏览驱动程序的 .NET API 参考。
AppContext 开关 配置兼容性和安全行为。
Microsoft.Data.SqlClient GitHub 存储库 阅读驱动源代码、发布说明和示例。
Microsoft.Data.SqlClient 示例 浏览 C# 驱动 API 的示例。
.NET 运行时 GitHub 仓库 阅读 .NET 运行时库的源代码。

请求功能

要请求某个功能,请在 Microsoft.Data.SqlClient 的 GitHub 仓库中打开一个问题。