Quickstart: Verbinden und Abfragen mit Microsoft.Data.SqlClient

In diesem Quickstart baust du eine .NET-Konsolen-App mit Microsoft. Data.SqlClient 7.1.1.

Du startest mit einem leeren Ordner, dem .NET SDK und einer SQL Server- oder Azure SQL-Datenbank, die du von deinem Computer aus erreichen kannst. Man beendet mit einer Konsolen-App, die eine Tabelle erstellt, zwei Zeilen mit Parametern einfügt und sie zurückliest.

Dabei:

  • Liest seine Verbindungszeichenfolge aus einer Umgebungsvariable statt aus dem Quellcode.
  • Öffnet eine Verbindung asynchron.
  • Verwendet Parameter für jeden Wert, den er an die Datenbank sendet.
  • Behandelt SQL-Fehler und Abbrüche.

Um denselben Datenzugriff in eine Web-API einzubauen, finden Sie unter Quickstart: Use Microsoft.Data.SqlClient in einer ASP.NET Core-App. Es verwendet dieselbe Tabelle.

Voraussetzungen

  • Das .NET 10 SDK oder ein später unterstütztes .NET SDK. Das SDK läuft unter Windows, Linux und macOS. Das SDK erstellt außerdem die .NET Framework-Version des Samples, die nur unter Windows läuft und .NET Framework 4.8.1 benötigt. Verwenden Sie die .NET-Version für neue Entwicklungen.
  • Ein Code-Editor. Du kannst Visual Studio, Visual Studio Code oder jeden beliebigen Editor zusammen mit der .NET-CLI verwenden. Dieser Artikel verwendet die .NET-CLI.
  • Eine Datenbank, zu der du eine Verbindung herstellen kannst. Wenn du noch keines hast, erstelle es mit den folgenden Optionen.

Erstellen einer SQL-Datenbank

Erstellen oder verbinden Sie sich mit einer SQL-Datenbank auf einer der folgenden Plattformen:

Datenbankberechtigungen

Die App erstellt ihre eigene Tabelle, sodass du keine Beispieldaten brauchst. Die Datenbankidentität benötigt die Berechtigung, um sich zu verbinden und eine Tabelle zu erstellen, einzufügen und daraus auszuwählen.

Für die SQL-Datenbank in Microsoft Fabric kopieren Sie die Server- und Datenbanknamen aus dem SQL-Datenbankelement. Nutze nicht den SQL-Analytics-Endpunkt. Die Identität benötigt die Berechtigung zum Lesen des Elements, die durch eine Arbeitsbereichsrolle oder eine Elementberechtigung gewährt werden kann. Weitere Informationen finden Sie unter Authentifizierung in SQL-Datenbank. SQL-Authentifizierung wird nicht unterstützt.

Für Azure SQL-Datenbank konfigurieren Sie Microsoft Entra ID-Authentifizierung und Datenbankzugriff.

Erstelle das Projekt

Führe in einem leeren Ordner folgende Befehle aus:

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

Das Erweiterungspaket stellt die Microsoft Entra-Authentifizierungsmodi des Treibers bereit, wie z. B. Active Directory Default. Wenn Ihre App nur SQL-Authentifizierung oder integrierte Windows-Authentifizierung verwendet, können Sie Microsoft.Data.SqlClient.Extensions.Azure weglassen. Wenn du beide Pakete verwendest, behalte ihre Versionen gleich. Für weitere Installationsoptionen siehe Installieren, aktualisieren und bereitstellen von Microsoft.Data.SqlClient.

Konfigurieren Sie die Verbindung

Setze die SQL_CONNECTION_STRING Umgebungsvariable für deine Datenbank. Fügen Sie kein Passwort, kein Zugriffstoken und keine Verbindungszeichenfolge für die Produktion in den Quellcode ein.

Wählen Sie einen dieser Ausgangspunkte und ersetzen Sie die Platzhalter.

Azure SQL oder SQL-Datenbank in Fabric mit Microsoft Entra ID

Melden Sie sich mit einer Microsoft Entra-Identität an, die Zugriff auf die Datenbank hat. Für lokale Entwicklung verwenden Sie ein Entwickler-Tool wie die Azure CLI:

az login

Kopiere die genauen Server- und Datenbanknamen aus der Azure SQL-Datenbank oder dem SQL-Datenbank-Element in Fabric. Für PowerShell:

$env:SQL_CONNECTION_STRING = 'Server=tcp:<server>,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict;MultiSubnetFailover=true;Connect Timeout=30'

Für Bash:

export SQL_CONNECTION_STRING='Server=tcp:<server>,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict;MultiSubnetFailover=true;Connect Timeout=30'

Für eine in Azure gehostete App gewähren Sie der verwalteten Identität Datenbankzugriff und verwenden dann Authentication=Active Directory Managed Identity. Für weitere Optionen siehe Microsoft Entra-Authentifizierung mit Microsoft.Data.SqlClient.

SQL Server mit SQL-Authentifizierung

Nutzen Sie den Server, Port, Datenbank und Login für Ihre SQL Server-Instanz. Das folgende Beispiel gilt für eine lokale Entwicklungsinstanz, die kein vertrauenswürdiges Zertifikat hat. Für PowerShell:

$env:SQL_CONNECTION_STRING = 'Server=tcp:<server>,1433;Database=<database>;User ID=<user-id>;Password=<password>;Encrypt=true;TrustServerCertificate=true;Connect Timeout=30'

Für 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 Überspringt die Serverzertifikatsvalidierung. Verwende es nur mit einer lokalen Entwicklungsinstanz, die kein vertrauenswürdiges Zertifikat hat. Für gemeinsam genutzte oder Produktions-SQL Server-Instanzen installieren Sie ein Zertifikat, dem der Client vertraut, verwenden Sie den Servernamen auf diesem Zertifikat und entfernen Sie TrustServerCertificate=true. Weitere Informationen finden Sie unter Verschlüsselungs- und Zertifikatüberprüfung in Microsoft.Data.SqlClient.

Wenn Ihre Umgebung Windows-integrierte Authentifizierung oder Kerberos unterstützt, ersetzen Sie User ID und Password durch Integrated Security=true. Für Einrichtungsanforderungen siehe SQL Server und Windows Authentication.

Hinzufügen des Codes

Ersetzen Sie den Inhalt von Program.cs durch den folgenden Code:

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

App starten

Führen Sie die App aus:

dotnet run

Beim ersten Start der App ist die Tabelle leer und die Ausgabe sieht so aus:

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)

Deine Zeitstempel unterscheiden sich. Jeder spätere Durchlauf fügt zwei weitere Zeilen hinzu, sodass die IDs dort fortgesetzt werden, wo der letzte Durchlauf endete.

Wenn die App keine Verbindung herstellen kann, druckt sie die SQL-Fehlernummer, die Client-Verbindungs-ID, die Fehlermeldung und die innere Ausnahmemeldung aus und beendet sich dann mit Code 3. Für häufige Fehler siehe Fehlersuche.

Funktionsweise des Codes

  • OpenAsync, ExecuteNonQueryAsync, ExecuteReaderAsync, ReadAsync und CancellationToken alle erhalten dasselbe ExecuteScalarAsync. Drücke Strg+C, um den laufenden Vorgang abzubrechen.
  • Der Einfügebefehl wird einmal erstellt und für jede Nachricht einmal ausgeführt. Nur der Parameterwert ändert sich.
  • Die Parametertypen und -größen stimmen mit den Tabellenspalten überein. Parameter senden Werte separat vom SQL-Text, was verhindert, dass diese Werte den Befehl ändern, und SQL Server dabei hilft, Abfragepläne wiederzuverwenden.
  • OUTPUT INSERTED.Id gibt den neuen Identity-Wert zurück, also gibt ExecuteScalarAsync die ID ohne eine zweite Abfrage zurück.
  • await using gibt die Befehle, den Reader und die Verbindung frei, selbst wenn eine Ausnahme eintritt. Beim Freigeben der Verbindung wird sie an den Verbindungspool zurückgegeben. Die .NET Framework-Version verwendet using-Blöcke, da diese Typen IAsyncDisposable unter .NET Framework nicht implementieren.
  • SqlException.Number erkennt den Fehler und ClientConnectionId ermöglicht es Ihnen, einen Clientausfall mit serverseitigen Protokollen abzugleichen. Bei Verbindungsfehlern unter Linux und macOS ist die Ursache oft nur in InnerException sichtbar, wie zum Beispiel ein Fehler bei der Zertifikatsvalidierung hinter dem generischen error: 35 - An internal exception was caught.

Troubleshoot

Fehler oder Symptom Was soll überprüft werden? Mehr erfahren
The certificate chain was issued by an authority that is not trustedauf Windows. Unter Linux und macOS gilt error: 35 - An internal exception was caught, gefolgt von der inneren Ausnahme Certificate failed chain validation mit UntrustedRoot. Das Serverzertifikat wird vom Client nicht als vertrauenswürdig eingestuft, oder der Servername in der Verbindungszeichenfolge stimmt nicht mit dem Zertifikat überein. Installieren Sie ein vertrauenswürdiges Zertifikat. Verwenden Sie TrustServerCertificate=true nur mit einer lokalen Entwicklungsinstanz. Verschlüsselung und Zertifikatsvalidierung bei Microsoft. Data.SqlClient
SQL error 18456 mit Login failed for user Der Benutzername, das Passwort oder der Datenbankname ist falsch, oder der Login hat keinen Zugriff auf die Datenbank. Für Microsoft Entra ID überprüfen Sie, ob die Identität als Datenbankbenutzer hinzugefügt wurde. Leitfaden zur Problembehandlung bei SqlClient
A network-related or instance-specific error occurred mit error: 26, error: 40oder The wait operation timed out. Unter Linux und macOS zeigt SQL error 258 ein Timeout mit error: 35, gefolgt von der inneren Ausnahme The connection attempt timed out. Der Servername oder Port ist falsch, der Server akzeptiert keine entfernten TCP-Verbindungen oder eine Firewall blockiert den Port. Für Azure SQL solltest du die Server-Firewall-Regeln überprüfen. Leitfaden zur Problembehandlung bei SqlClient
System.ArgumentException: Cannot find an authentication provider for 'ActiveDirectoryDefault' Die Verbindungszeichenfolge verwendet den Authentifizierungsmodus Active Directory, aber das Projekt verweist nicht auf Microsoft.Data.SqlClient.Extensions.Azure. Füge das Paket mit derselben Version wie Microsoft.Data.SqlClienthinzu. Die Microsoft Entra-Authentifizierung wechselt in 7.0 auf ein Erweiterungspaket
CS0234: The type or namespace name 'Data' does not exist in the namespace 'Microsoft' Das Projekt verweist nicht auf das Paket Microsoft.Data.SqlClient. Führe den dotnet add package-Befehl in dem Ordner aus, der die Projektdatei enthält. Microsoft.Data.SqlClient installieren, aktualisieren und bereitstellen
Berichte für ein transitives Paket NU1902 oder NU1903 wiederherstellen Für ein Paket, von dem der Treiber abhängt, wurde eine Sicherheitswarnung veröffentlicht. Aktionen, wenn Pakete mit bekannten Schwachstellen gemeldet werden

Bereinigen von Ressourcen

Die Tabelle bleibt in deiner Datenbank, nachdem die App beendet wurde. Wenn Sie nicht planen, mit dem ASP.NET Core Quickstart fortzufahren, der dieselbe Tabelle verwendet, löschen Sie sie mit einem beliebigen Abfragetool:

DROP TABLE IF EXISTS dbo.SqlClientQuickstart;

Dann lösche den Projektordner. Aus dem Elternordner, für PowerShell:

Remove-Item -Recurse -Force SqlClientQuickstart

Für Bash:

rm -rf SqlClientQuickstart

Lösche die Umgebungsvariable, damit der Verbindungszeichenfolge nicht in deiner Shell-Session bleibt. Für PowerShell führe Remove-Item Env:\SQL_CONNECTION_STRING aus. Führen Sie für Bash unset SQL_CONNECTION_STRING aus.

Verwenden Sie das Muster in einer Anwendung

Halten Sie diese Grenzen ein, wenn Sie das Beispiel in eine API, einen Dienst, eine Desktop-App oder einen Hintergrundprozess übertragen:

  • Lade die Verbindungsinformationen über das Konfigurationssystem der App.
  • Öffnen Sie eine Verbindung für eine kurze Arbeitseinheit und schließen Sie sie dann wieder.
  • Übergeben Sie ein CancellationToken via Öffnen-, Befehls- oder Leser-Aufrufe.
  • Setze Kommando-Timeouts basierend auf der Operation.
  • Verwenden Sie Parameter für jeden Wert, der außerhalb der SQL-Anweisung kommt.
  • Protokollieren Sie SqlException.Number und ClientConnectionId, ohne Zugangsdaten oder Zugriffstoken zu protokollieren.
  • Erneute Versuche nur bei vorübergehenden Ausfällen hinzufügen und nur, wenn die Wiederholung der Operation sicher ist.

Nächste Schritte