快速入門:使用 Microsoft.Data.SqlClient 連線並查詢

在這個快速入門中,你要使用 Microsoft.Data.SqlClient 7.1.1 建置一個 .NET 控制台應用程式。

你從一個空資料夾、.NET SDK 和一個可以從電腦存取的 SQL Server 或 Azure SQL 資料庫開始。 最後你會用一個主控台應用程式建立表格,使用參數插入兩個資料列,然後讀回來。

在這個過程中,應用程式:

  • 它從環境變數讀取 連接字串,而非原始碼。
  • 非同步開啟連線。
  • 它對每個傳送給資料庫的值都使用參數。
  • 處理 SQL 錯誤與取消。

要將相同的資料存取建置到 Web API,請參閱快速入門:在 ASP.NET Core 應用程式中使用 Microsoft.Data.SqlClient。 它使用同一張表格。

Prerequisites

  • .NET 10 SDK 或後來支援的 .NET SDK。 SDK 可運行於 Windows、Linux 及 macOS 上。 SDK 也建置了範例的 .NET Framework 版本,該版本僅能在 Windows 上執行,且需要 .NET Framework 4.8.1。 新開發時使用.NET版本。
  • 一個程式碼編輯器。 你可以搭配 .NET CLI 一起使用 Visual Studio、Visual Studio Code 或任何編輯器。 本文使用 .NET CLI。
  • 一個你可以連接的資料庫。 如果你還沒有帳戶,請使用以下選項建立一個。

建立 SQL 資料庫

在以下平台建立或連接 SQL 資料庫:

資料庫權限

App 會建立自己的表格,所以不需要樣本資料。 資料庫識別需要具備連線,以及建立資料表、向資料表插入資料,並從資料表選取資料的權限。

在 Microsoft Fabric 的 SQL 資料庫中,從 SQL 資料庫項目複製伺服器名稱與資料庫名稱。 不要使用 SQL Analytics 端點。 該身分需要項目的讀取權限,而工作區角色或項目權限可提供此權限。 欲了解更多資訊,請參閱 SQL 資料庫中的認證。 不支援 SQL 認證。

對於 Azure SQL Database,請設定 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 資料庫的環境變數。 不要在原始碼中放入密碼、存取權杖或正式環境的連線字串。

選擇其中一個起始點並替換佔位符。

Azure SQL 或 Fabric 中搭配 Microsoft Entra ID 的 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,請將 Password 和 User ID 替換為 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、ExecuteNonQueryAsync、ExecuteScalarAsync、ExecuteReaderAsync 和 ReadAsync 都獲得相同的 CancellationToken。 按 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,後面接著的是含有 UntrustedRoot 的內部例外 Certificate failed chain validation。 伺服器憑證不被客戶端信任,或者 連接字串 中的伺服器名稱與憑證不符。 安裝一個受信任的憑證。 僅可搭配本機開發執行個體使用 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 上,逾時會顯示含有 error: 35 的 SQL error 258,後面接著內部例外 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,但不要記錄認證資訊或存取權杖。
  • 僅在發生暫態故障時才加入重試機制,且僅在可安全重複執行該作業時才這麼做。

下一步