Microsoft.Data.SqlClient 的连接字符串

Microsoft.Data.SqlClient 连接字符串是一个用分号分隔的 keyword=value 对列表。 传给 SqlConnection 或 SqlConnectionStringBuilder:

Server=tcp:sql.example.com,1433;Database=Orders;Integrated Security=true;Encrypt=Strict

连接字符串可以回答四个问题:

  1. 应用使用哪台服务器和数据库?
  2. 应用程序以哪个身份运行?
  3. 客户端如何验证服务器证书?
  4. 工作负载需要哪种连接行为?

本文介绍这些选择,以及驱动程序读取文本时所使用的规则。 对于每个关键字及其同义词和默认值,请参阅连接选项。 要在代码中创建和更改连接字符串,请参见 连接字符串构建器。

选择一种认证模式

使用适合部署的模式。 将每个占位符(例如 <server>)替换为你的值。

Environment 模式 连接字符串
使用域或本地 Windows 标识的 Windows 上的 SQL Server Windows 集成身份验证 Server=<server>;Database=<database>;Integrated Security=true;Encrypt=true
托管在 Azure 中并连接到 Azure SQL 的应用程序 Microsoft Entra ID 托管标识 Server=tcp:<server>.database.windows.net,1433;Database=<database>;Authentication=Active Directory Managed Identity;Encrypt=Strict
连接到 Azure SQL 的开发人员工作站 Microsoft Entra ID 默认凭证链 Server=tcp:<server>.database.windows.net,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict
开发者工作站连接 Microsoft Fabric 中的 SQL 数据库 Microsoft Entra ID 默认凭证链 Server=tcp:<server>,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict
连接到 Azure SQL 的交互式桌面工具 Microsoft Entra ID 交互式认证 Server=tcp:<server>.database.windows.net,1433;Database=<database>;Authentication=Active Directory Interactive;Encrypt=Strict
需要SQL认证的环境 来自机密存储的用户名和密码 Server=<server>;Database=<database>;User ID=<user>;Password=<password>;Encrypt=true

Windows 集成身份验证以进程的身份进行连接。 对于桌面或控制台应用,通常是登录用户。 对于网页应用或 Windows 服务,则是应用池或服务账户。 模拟可以改变身份。 给你的应用实际使用的身份赋予登录权限和数据库权限。

这三种Windows集成认证形式是等价的:

Server=sql.example.com;Database=Orders;Integrated Security=true;Encrypt=true
Server=sql.example.com;Database=Orders;Integrated Security=SSPI;Encrypt=true
Server=sql.example.com;Database=Orders;Trusted_Connection=yes;Encrypt=true

如果字符串设置了 Integrated Security=true,同时也设置了 User ID 和 Password,驱动程序会使用 Windows 身份验证,并忽略用户名和密码。

Microsoft.Data.SqlClient 7.0 及更高版本需要版本匹配的 Microsoft.Data.SqlClient.Extensions.Azure 包,才能使用驱动程序提供的 Microsoft Entra ID 身份验证方法。 当应用代码提供访问令牌或访问令牌回调时,你就不需要这个包。

有关接受的 Authentication 值,请参阅身份验证选项。 认证还需要服务器上的数据库用户、权限以及身份配置。 关于设置步骤,请参见 Microsoft Entra ID 认证和 SQL Server 认证。

指定服务器和数据库

Server 和 Database 是最易读的关键词名称。 生成器会将它们写为规范等效形式:Data Source 和 Initial Catalog。 这四个名称均可在连接字符串中使用。

将 Server 设置为以下其中一种形式:

Form Example Use
主机名 Server=sql.example.com 默认实例在1433端口。
主机名和端口 Server=tcp:sql.example.com,1433 一个特定的TCP端口。 用逗号分隔端口,而不是冒号。
命名实例 Server=sql.example.com\SALES 一个命名实例。 驱动程序向 UDP 端口 1434 上的 SQL Server 浏览器服务请求端口。
本地服务器 Server=(local) 或 Server=. 本地电脑上的默认实例。
LocalDB Server=(localdb)\MSSQLLocalDB SQL Server Express LocalDB 在 Windows 上。 即使使用 Encrypt=Mandatory,连接也不会加密,并且 Encrypt=Strict 会失败。
命名管道 Server=np:\\sql.example.com\pipe\sql\query Windows上的命名管道连接。

在生产环境中,使用 tcp:、完全限定的主机名以及显式指定的端口。 使用与服务器证书匹配的DNS名称,而非IP地址,因为证书验证会将连接字符串中的服务器名称与证书中的名称进行比较。

使用 SQL 身份验证连接到 Azure SQL 数据库,且用户名格式为 user@servername 时,servername 部分必须与 Server 中的服务器匹配。

对于可用性组侦听器或故障转移群集实例,另请查看连接选项中的 Multi Subnet Failover。

配置加密和证书验证

Encrypt 关键字接受以下值,不区分大小写:

Value 生成器值 Meaning
Strict Strict 使用TDS 8.0。 登录前加密连接,并且始终验证服务器证书。
Mandatory、true、yes True 加密连接。 此值为默认值。
Optional、false、no False 只有当服务器需要加密时,才会加密整个连接。 当服务器支持加密但不强制时,只加密登录包。

当服务器支持 TDS 8.0 并且有客户端可以验证的证书时使用 Strict 。 Azure SQL 数据库 和 Microsoft Fabric 中的 SQL 数据库都支持它。 即使使用 Mandatory,LocalDB 连接也不会加密,并且 Strict 会失败。

Encrypt 和 Trust Server Certificate 值按如下方式组合:

加密 信任服务器证书 Result
Optional false 当服务器需要加密时,整个连接都会被加密,服务器证书必须通过验证。 否则,连接将失败。 当服务器支持加密但不强制时,只有登录包被加密,驱动不会验证服务器证书,除非连接使用 AccessToken 或 AccessTokenCallback。 当服务器不支持加密时,什么都不会被加密。
Optional true 当服务器需要加密时,整个连接都会被加密。 当服务器支持加密但不强制时,只有登录包被加密。 驱动程序不验证服务器证书。
Mandatory false 仅当服务器证书验证通过时,才会进行加密。 否则,连接将失败。
Mandatory true 加密总是会发生,但驱动程序不会验证服务器证书。
Strict 已忽略 始终会进行加密,并且服务器证书必须经过验证。 否则,连接将失败。

不要通过设置 Trust Server Certificate=true 来解决生产环境中的连接错误。 它会加密通道,但不会确认服务器的身份。 限制在没有可信证书的开发环境中使用。

当 Data Source 中的服务器名称与证书不匹配时,就将 Host Name In Certificate 设置为证书中的名称。 只有当服务器名称不匹配时,SqlClient 才会检查它,而且它不会固定证书。 要只接受一个特定证书,请将 Server Certificate 设置为 PEM、DER 或 CER 文件的路径:

Server=tcp:sql.example.com,1433;Encrypt=Strict;Host Name In Certificate=sqlhost.example.com
Server=tcp:sql.example.com,1433;Encrypt=Strict;Server Certificate=C:\certificates\server.cer

完整的验证规则请参见 加密与证书验证。

使用连接池

轮询默认处于打开状态。 打开 SqlConnection 时,驱动程序会从与该连接匹配的池中获取一个物理连接。 当你关闭或丢弃连接时,物理连接会返回到池中,而不是关闭。 共用连接打开时会跳过网络连接、TLS 握手和登录。

遵循以下规则:

  • 在需要时再打开连接,并在完成后立即释放它,可使用 using 或 await using。 未释放的连接会一直处于被占用状态,连接池可能会耗尽。

  • 启动时先构建一次 连接字符串,然后重复使用。 池键包含连接字符串的确切文本,因此不同的关键词顺序、同义词或每个请求的值(如请求ID或用户名)会创建一个独立的池。 生成器会写出一种规范形式。 欲了解更多信息,请参见保留一个规范的连接字符串。

  • 在集成身份验证下,应为每个 Windows 标识、每个 SqlCredential 实例和每个 AccessToken 值分别准备一个独立的连接池。 使用驱动程序提供的 Authentication 方法,或复用同一个 AccessTokenCallback,而不是为每个连接设置 AccessToken。

  • 在调高 Max Pool Size(默认值为 100)之前,请先查找那些未被释放的连接。 当池中所有连接都在使用时,Open 最多等待 Connect Timeout,然后抛出 InvalidOperationException:

    Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.
    
  • 为每个池规划服务器容量。 每个进程,或 .NET 框架上的每个应用域,都有自己的池。 到服务器的连接数最多可达到 Max Pool Size 乘以每个进程中的连接池数量再乘以应用实例数量。

  • 不要通过设置 Pooling=false 来解决池问题。 每次打开都会执行一次完整登录。

要关闭空闲时间过长的池化连接,请参见 限制连接空闲时间。 有关池键、调整大小、清除和事务的信息,请参阅 SQL Server 连接池。

独立连接和命令设置

连接字符串控制着连接的建立和会话行为。 命令控制一个SQL操作。

Requirement 配置启用
允许建立连接或从连接池获取连接的时间 Connect Timeout 关键词
连接上命令的默认超时时间 Command Timeout 关键词
单个命令的超时时间 CommandTimeout
由呼叫方取消 CancellationToken 传递给异步方法
重试策略用于打开连接或执行命令 可配置的重试逻辑位于 SqlConnection 或 SqlCommand 上

更长的超时时间并不是重试逻辑。 暂停时间限制了等待时间。 重试会开始另一次尝试,而且必须有次数限制,并且可以安全地重复执行。

报告应用程序标识

Application Name 设置服务器通过 APP_NAME() 报告的名称。 每个部署的工作负载使用一个稳定名称。 为应用程序打开连接的框架和工具,也可以通过 RegisteredApplication 属性报告自身信息,但该属性没有对应的连接字符串关键字。 有关详细信息,请参阅报告应用程序标识。

安全地构建连接字符串

当代码添加或更改某个值时使用 SqlConnectionStringBuilder 。 不要将不受信任的文本加入连接字符串,因为该文本中的分号可能会添加或替换关键词。 生成器会验证值、将同义词映射为规范关键字,并为每个值加引号,使该值无法添加关键字。 示例请参见 连接字符串构建器。

代码外存储连接信息

从应用程序的配置系统加载连接字符串。 .NET 应用通常使用环境变量、本地开发的 user secrets、Azure 应用程序配置 和 Azure 密钥保管库。

遵循以下规则:

  • 不要提交密码、客户端秘密、访问令牌或生产连接字符串。
  • 更倾向于使用不需要在连接字符串中输入密码的认证方式。
  • 限制对配置源的访问。
  • 轮换已存储的机密,并重启或刷新会缓存这些机密的应用程序。
  • 不要给日志、异常、跟踪或遥测写入连接字符串。
  • 保持 Persist Security Info=false为默认,这样打开连接时不会通过其 ConnectionString 属性暴露密码。

关于 .NET 配置提供者,请参见 .NET 中的配置。 有关更多控制项,请参阅保护连接信息。

解析规则

驱动程序会应用以下规则:

  • 关键字不区分大小写。 DATABASE, Database, 和 database 是同一个关键词。
  • 许多关键词都有同义词。 将 Server 和 Data Source 设置为相同的值。 连接选项文章列出了每个关键词的同义词。
  • 当某个关键字出现多次时,以最后一个值为准。 同义词算作同一个关键词。
  • 驱动程序忽略关键词周围和未加引号的值周围的空格。
  • 尾部分号是可选的。
  • 驱动程序不认识的关键字会抛出 ArgumentException,并显示消息 Keyword not supported。

值可以区分大小写,具体取决于关键词。 密码是区分大小写的。 Encrypt=STRICT 和 Encrypt=strict 是一样的。

该程序展示了构建器如何规范关键词、解决重复以及引用特殊字符。 .NET Framework 选项卡使用 C# 7.3。 要创建运行样本的项目,请参见“创建项目”。

using Microsoft.Data.SqlClient;

// Synonyms and keyword case are normalized to canonical keywords.
var parsed = new SqlConnectionStringBuilder(
    "server=tcp:sql.example.com,1433;DATABASE=Orders;uid=app_user;encrypt=yes;timeout=30");
Console.WriteLine(parsed.ConnectionString);

// When a keyword repeats, the last value wins.
var duplicate = new SqlConnectionStringBuilder(
    "Server=sql.example.com;Database=Orders;Database=Archive");
Console.WriteLine($"InitialCatalog: {duplicate.InitialCatalog}");

// The builder quotes values that contain delimiters.
var quoted = new SqlConnectionStringBuilder
{
    DataSource = "sql.example.com",
    UserID = "app_user",
    Password = "a;b'c\"d",
};
Console.WriteLine(quoted.ConnectionString);
Console.WriteLine($"Round trip: {new SqlConnectionStringBuilder(quoted.ConnectionString).Password == quoted.Password}");

输出为:

Data Source=tcp:sql.example.com,1433;Initial Catalog=Orders;User ID=app_user;Connect Timeout=30;Encrypt=True
InitialCatalog: Archive
Data Source=sql.example.com;User ID=app_user;Password="a;b'c""d"
Round trip: True

第一行显示每个同义词被其规范关键字替换:server 替换为 Data Source,DATABASE 替换为 Initial Catalog,uid 替换为 User ID,timeout 替换为 Connect Timeout。

为值加引号

当值包含分号、以空格开头或结尾,或以引号开头或结尾时,用双引号(")或单引号(')包围。 在带引号的值内部,将包围引号写两次。

Value 连接字符串形式
a;b Password="a;b"
abc' Password="abc'"
say "hi" Password='say "hi"'
a;b'c"d Password="a;b'c""d"

引用规则很容易出错。 通过 SqlConnectionStringBuilder 属性设置值,并让生成器为它们加引号。 有关详细信息,请参阅安全生成连接字符串。

指定布尔值

取布尔值的关键字接受 true、false、yes 和 no,不区分大小写。 Integrated Security 也接受 sspi,这意味着 true。 生成器会写入 True 或 False。

使用来自其他驱动程序的关键字

Microsoft.Data.SqlClient 不接受 ODBC 或 OLE DB 关键词,例如 Driver 和 Provider。 当你从另一个驱动程序移动连接字符串时,移除这些关键词。 System.Data.SqlClient 连接字符串可在 Microsoft.Data.SqlClient 中使用,但有以下差异:

  • Encrypt 在 Microsoft.Data.SqlClient 中默认为 Mandatory。 没有受信任证书的服务器将无法通过证书验证。 在服务器上安装一个可信证书。
  • 在 .NET 上,Network Library、Connection Reset 和 Transparent Network IP Resolution 都不被支持。 将其删除。
  • 不支持 Context Connection=true。
  • Asynchronous Processing 不是受支持的关键字,并抛出 ArgumentException。 将其删除。 异步方法无需它也能工作。
  • 不支持 Type System Version=SQL Server 2000。 创建连接时会抛出ArgumentException。 使用 Latest、 SQL Server 2012、 SQL Server 2008或 SQL Server 2005。