在这个快速入门中,你将使用 Microsoft.Data.SqlClient 7.1.1 构建一个 .NET 控制台应用。
你从一个空文件夹、.NET SDK和一个可以从电脑访问的SQL Server或Azure SQL数据库开始。 最后用一个控制台应用创建表,插入带参数的两行,然后读取它们。
在这个过程中,应用:
- 它从环境变量中读取 连接字符串,而不是从源代码中读取。
- 异步开启连接。
- 它为发送到数据库的每个值使用参数。
- 处理 SQL 错误和取消操作。
要将相同的数据访问构建到 Web API 中,请参见快速入门:在 ASP.NET Core 应用中使用 Microsoft.Data.SqlClient。 它使用了同一张表格。
先决条件
- .NET 10 SDK 或更高版本且受支持的 .NET SDK。 该SDK可在Windows、Linux和macOS上运行。 SDK 还构建了 .NET Framework 版本的示例,该版本仅支持 Windows,且需要 .NET Framework 4.8.1。 新开发时使用.NET版本。
- 一个代码编辑器。 你可以使用Visual Studio、Visual Studio Code或任何编辑器配合.NET CLI。 本文使用 .NET CLI。
- 一个你可以连接的数据库。 如果你还没有,请通过以下选项创建一个。
创建 SQL 数据库
在以下平台之一创建或连接SQL数据库:
数据库权限
应用会创建自己的表格,所以你不需要样本数据。 数据库身份需要具备连接权限,以及创建表、向表中插入数据和从表中查询数据的权限。
对于 Microsoft Fabric 中的 SQL 数据库,从 SQL 数据库项中复制服务器名和数据库名称。 不要用SQL分析端点。 该标识需要项目读取权限,而工作区角色或项目权限均可授予该权限。 更多信息请参见 SQL数据库中的认证。 不支持SQL认证。
对于 Azure SQL 数据库,配置 Microsoft Entra ID 认证和数据库访问。
创建项目
在一个空文件夹中,执行以下命令:
dotnet new console --framework net10.0 --name SqlClientQuickstart
cd SqlClientQuickstart
dotnet add package Microsoft.Data.SqlClient --version 7.1.1
dotnet add package Microsoft.Data.SqlClient.Extensions.Azure --version 7.1.1
扩展包提供驱动程序的 Microsoft Entra 认证模式,例如 Active Directory Default。 如果你的应用只使用 SQL 认证或 Windows 集成认证,可以省略 Microsoft.Data.SqlClient.Extensions.Azure。 使用两个软件包时,保持它们的版本相同。 有关其他安装选项,请参见安装、更新和部署 Microsoft.Data.SqlClient。
配置连接
为你的数据库设置 SQL_CONNECTION_STRING 环境变量。 不要在源代码中写入密码、访问令牌或生产环境连接字符串。
选择这些起始点之一并替换占位符。
使用 Microsoft Entra ID 的 Azure SQL 或 Fabric 中的 SQL 数据库
使用拥有数据库访问权限的 Microsoft Entra 身份登录。 本地开发时,可以使用开发者工具,如 Azure CLI:
az login
从Azure SQL数据库或Fabric中的SQL数据库项复制准确的服务器和数据库名称。 对于 PowerShell:
$env:SQL_CONNECTION_STRING = 'Server=tcp:<server>,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict;MultiSubnetFailover=true;Connect Timeout=30'
对于 Bash:
export SQL_CONNECTION_STRING='Server=tcp:<server>,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict;MultiSubnetFailover=true;Connect Timeout=30'
对于托管在 Azure 中的应用,授予其托管身份数据库访问权限,然后使用 Authentication=Active Directory Managed Identity。 有关其他选项,请参见 使用 Microsoft.Data.SqlClient 的 Microsoft Entra 身份验证。
SQL Server 与 SQL 认证
使用适用于你的 SQL Server 实例的服务器、端口、数据库和登录信息。 以下示例是一个没有受信任证书的本地开发实例。 对于 PowerShell:
$env:SQL_CONNECTION_STRING = 'Server=tcp:<server>,1433;Database=<database>;User ID=<user-id>;Password=<password>;Encrypt=true;TrustServerCertificate=true;Connect Timeout=30'
对于 Bash:
export SQL_CONNECTION_STRING='Server=tcp:<server>,1433;Database=<database>;User ID=<user-id>;Password=<password>;Encrypt=true;TrustServerCertificate=true;Connect Timeout=30'
Caution
TrustServerCertificate=true 跳过服务器证书验证。 只在没有受信任证书的本地开发实例中使用。 对于共享或生产型 SQL Server 实例,安装客户端信任的证书,使用该证书上的服务器名称,然后移除 TrustServerCertificate=true。 有关详细信息,请参阅 Microsoft.Data.SqlClient 中的加密和证书验证。
如果你的环境支持 Windows 集成认证或 Kerberos,请将 User ID 和 Password 替换为 Integrated Security=true。 关于设置要求,请参见 SQL Server 和 Windows 身份验证。
添加代码
用以下代码替换 Program.cs 的内容:
using System.Data;
using Microsoft.Data.SqlClient;
string? connectionString =
Environment.GetEnvironmentVariable("SQL_CONNECTION_STRING");
if (string.IsNullOrWhiteSpace(connectionString))
{
Console.Error.WriteLine(
"Set the SQL_CONNECTION_STRING environment variable.");
return 1;
}
using var cancellation = new CancellationTokenSource();
Console.CancelKeyPress += (_, eventArgs) =>
{
eventArgs.Cancel = true;
cancellation.Cancel();
};
try
{
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellation.Token);
const string createTableSql = """
IF OBJECT_ID(N'dbo.SqlClientQuickstart', N'U') IS NULL
BEGIN
CREATE TABLE dbo.SqlClientQuickstart
(
Id int IDENTITY(1, 1) PRIMARY KEY,
Message nvarchar(200) NOT NULL,
CreatedAt datetimeoffset NOT NULL
CONSTRAINT DF_SqlClientQuickstart_CreatedAt
DEFAULT sysdatetimeoffset()
);
END;
""";
await using (var createCommand =
new SqlCommand(createTableSql, connection) { CommandTimeout = 30 })
{
await createCommand.ExecuteNonQueryAsync(cancellation.Token);
}
const string insertSql = """
INSERT INTO dbo.SqlClientQuickstart (Message)
OUTPUT INSERTED.Id
VALUES (@message);
""";
string[] messages =
[
"Hello from Microsoft.Data.SqlClient",
"Parameters keep values out of the SQL text"
];
int firstId = 0;
await using (var insertCommand =
new SqlCommand(insertSql, connection) { CommandTimeout = 30 })
{
SqlParameter messageParameter =
insertCommand.Parameters.Add("@message", SqlDbType.NVarChar, 200);
foreach (string message in messages)
{
messageParameter.Value = message;
int id = (int)(await insertCommand.ExecuteScalarAsync(
cancellation.Token))!;
Console.WriteLine($"Inserted row {id}.");
firstId = firstId == 0 ? id : firstId;
}
}
const string querySql = """
SELECT Id, Message, CreatedAt
FROM dbo.SqlClientQuickstart
WHERE Id >= @firstId
ORDER BY Id;
""";
await using var queryCommand =
new SqlCommand(querySql, connection) { CommandTimeout = 30 };
queryCommand.Parameters.Add("@firstId", SqlDbType.Int).Value = firstId;
await using SqlDataReader reader =
await queryCommand.ExecuteReaderAsync(cancellation.Token);
while (await reader.ReadAsync(cancellation.Token))
{
Console.WriteLine(
$"{reader.GetInt32(0)}: {reader.GetString(1)} " +
$"(created {reader.GetDateTimeOffset(2):u})");
}
return 0;
}
catch (OperationCanceledException)
{
Console.Error.WriteLine("The operation was canceled.");
return 2;
}
catch (SqlException ex)
{
Console.Error.WriteLine(
$"SQL error {ex.Number}, connection {ex.ClientConnectionId}: " +
ex.Message);
if (ex.InnerException is not null)
{
Console.Error.WriteLine(ex.InnerException.Message);
}
return 3;
}
运行应用
运行应用:
dotnet run
第一次运行应用时,表是空的,输出如下:
Inserted row 1.
Inserted row 2.
1: Hello from Microsoft.Data.SqlClient (created 2026-10-20 20:56:10Z)
2: Parameters keep values out of the SQL text (created 2026-10-20 20:56:10Z)
你的时间戳不同。 每次后续运行都会增加两行,因此ID从上一次运行中延续。
如果应用无法连接,它会打印 SQL 错误号、客户端连接 ID、错误信息和内部异常信息,然后以退出代码 3 退出。 常见问题请参见 故障排除。
代码的工作原理
-
OpenAsync、ReadAsync、CancellationToken、ExecuteReaderAsync和ExecuteScalarAsync都获得相同的ExecuteNonQueryAsync。 按 Ctrl+C 取消当前操作。 - 插入命令只创建一次,对每条消息运行一次。 只有参数值会变。
- 参数类型和大小与表列相匹配。 参数值会与 SQL 文本分开发送,防止这些值更改命令,并帮助 SQL Server 重用查询计划。
-
OUTPUT INSERTED.Id返回新的标识值,因此ExecuteScalarAsync返回该 ID,无需再次查询。 -
await using即使出现异常,也会释放命令、读取器和连接。 释放连接后,它会被返回连接池。 .NET Framework 版本使用using块,因为这些类型在 .NET Framework 上未实现IAsyncDisposable。 -
SqlException.Number它能识别错误,并ClientConnectionId使客户端故障与服务器端日志相匹配。 对于 Linux 和 macOS 上的连接失败,原因通常仅显示在InnerException中,例如隐藏在通用error: 35 - An internal exception was caught后面的证书验证失败。
Troubleshoot
| 错误或症状 | 需要检查的事项 | 更多信息 |
|---|---|---|
The certificate chain was issued by an authority that is not trusted在Windows上。 在 Linux 和 macOS 上,error: 35 - An internal exception was caught后跟内部异常Certificate failed chain validation,并带有UntrustedRoot。 |
服务器证书不被客户端信任,或者连接字符串中的服务器名称与证书不匹配。 安装受信任的证书。 仅可与本地开发实例配合使用 TrustServerCertificate=true |
Microsoft.Data.SqlClient 中的加密和证书验证 |
SQL error 18456 与 Login failed for user |
用户名、密码或数据库名称有误,或者登录用户没有数据库访问权限。 对于 Microsoft Entra ID,检查该身份是否被添加为数据库用户。 | SqlClient 故障排除指南 |
A network-related or instance-specific error occurred 使用 error: 26、error: 40或The wait operation timed out。 在 Linux 和 macOS 上,超时显示 SQL error 258 为 error: 35,后面是内部例外 The connection attempt timed out。 |
服务器名称或端口错误,服务器不接受远程TCP连接,或者防火墙封锁了端口。 对于Azure SQL,请检查服务器防火墙规则。 | SqlClient 故障排除指南 |
System.ArgumentException: Cannot find an authentication provider for 'ActiveDirectoryDefault' |
连接字符串 使用Active Directory认证模式,但项目不引用 Microsoft.Data.SqlClient.Extensions.Azure。 将与 Microsoft.Data.SqlClient 版本相同的软件包添加进来 |
Microsoft Entra 认证在 7.0 版本中迁移到扩展包 |
CS0234: The type or namespace name 'Data' does not exist in the namespace 'Microsoft' |
项目未引用该 Microsoft.Data.SqlClient 软件包。 从包含项目文件的文件夹里执行 dotnet add package 命令。 |
安装、更新并部署 Microsoft。Data.SqlClient |
恢复某个传递包的报告 NU1902 或 NU1903 |
驱动程序依赖的软件包已发布公告。 | 当报告已知漏洞的包时的操作 |
清理资源
应用退出后,表格会留在你的数据库中。 如果你不打算继续使用相同表的 ASP.NET Core 快速入门,可以用任意查询工具删除该表:
DROP TABLE IF EXISTS dbo.SqlClientQuickstart;
然后删除项目文件夹。 在父文件夹中,使用 PowerShell:
Remove-Item -Recurse -Force SqlClientQuickstart
对于 Bash:
rm -rf SqlClientQuickstart
清除环境变量,这样连接字符串就不会留在你的shell会话里。 对于PowerShell,运行 Remove-Item Env:\SQL_CONNECTION_STRING. 对于 Bash,运行 unset SQL_CONNECTION_STRING。
在应用中使用该图案
当你将样本迁移到API、服务、桌面应用或后台工作工具时,请遵守以下界限:
- 通过应用的配置系统加载连接信息。
- 打开一个连接来完成一小段工作,然后将其释放。
- 通过 open、command 和 reader 调用传递
CancellationToken。 - 根据具体操作设置命令超时时间。
- 为来自SQL语句外的每个值使用参数。
- 记录
SqlException.Number和ClientConnectionId,且不记录凭证或访问令牌。 - 仅针对瞬时性故障实施重试,并且仅当重复执行该操作是安全的时才这样做。