Avvio rapido: Connettiti e consulta con Microsoft.Data.SqlClient

In questo avvio rapido, crei un'app console .NET con Microsoft.Data.SqlClient 7.1.1.

Si parte da una cartella vuota, dall'SDK .NET e da un database SQL Server o Azure SQL a cui puoi accedere dal computer. Finisci con un'app console che crea una tabella, inserisce due righe con parametri e li rilegge.

Durante il processo, l'app:

  • Legge la sua stringa di connessione da una variabile di ambiente invece che dal codice sorgente.
  • Apre una connessione in modo asincrono.
  • Utilizza parametri per ogni valore che invia al database.
  • Gestisce errori SQL e annullamento.

Per integrare lo stesso accesso ai dati in un'API web, vedi Quickstart: Usa Microsoft. Data.SqlClient in un'app ASP.NET Core. Usa la stessa tabella.

Prerequisiti

  • L'SDK .NET 10 o un SDK .NET supportato successivo. L’SDK gira su Windows, Linux e macOS. L'SDK compila anche la versione .NET Framework dell'esempio, che gira solo su Windows e necessita di .NET Framework 4.8.1. Usa la versione .NET per nuovi sviluppi.
  • Un editor di codice. Puoi usare Visual Studio, Visual Studio Code o qualsiasi editor insieme alla CLI .NET. Questo articolo utilizza la CLI .NET.
  • Un database a cui puoi connetterti. Se non ne hai uno, creane uno usando le seguenti opzioni.

Creare un database SQL

Crea o collegati a un database SQL su una delle seguenti piattaforme:

Autorizzazioni per il database

L'app crea la propria tabella, quindi non serve il campione di dati. L'identità del database necessita del permesso per connettersi e creare, inserire e selezionare da una tabella.

Per il database SQL in Microsoft Fabric, copia i nomi del server e del database dall'elemento SQL database. Non usare l'endpoint di SQL analytics. L'identità richiede l'autorizzazione di lettura dell'elemento, che può essere fornita da un ruolo dell'area di lavoro o da un'autorizzazione a livello di elemento. Per ulteriori informazioni, vedi Autenticazione nel database SQL. L'autenticazione SQL non è supportata.

Per database SQL di Azure, configura l'autenticazione e l'accesso al database di Microsoft Entra ID.

Creare il progetto

In una cartella vuota, esegui questi comandi:

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

Il pacchetto di estensione fornisce le modalità di autenticazione Microsoft Entra del driver, come Active Directory Default. Se la tua app utilizza solo l'autenticazione SQL o l'autenticazione integrata Windows, puoi omettere Microsoft.Data.SqlClient.Extensions.Azure. Quando usi entrambi i pacchetti, mantieni le loro versioni uguali. Per altre opzioni di installazione, vedi Installa, aggiorna e distribuisci Microsoft.Data.SqlClient.

Configura la connessione

Imposta la SQL_CONNECTION_STRING variabile ambiente per il tuo database. Non inserire una password, un token di accesso o una stringa di connessione di produzione nel codice sorgente.

Scegli uno di questi punti di partenza e sostituisci i segnaposto.

Azure SQL o database SQL in Fabric con Microsoft Entra ID

Accedi con un'identità Microsoft Entra che abbia accesso al database. Per lo sviluppo locale, usa uno strumento per sviluppatori come interfaccia della riga di comando di Azure:

az login

Copia i nomi esatti dei server e del database dal database Azure SQL o dall'elemento del database SQL in Fabric. Per PowerShell:

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

Per Bash:

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

Per un'app ospitata in Azure, concedi alla sua identità gestita l'accesso al database, quindi usa Authentication=Active Directory Managed Identity. Per altre opzioni, vedi autenticazione Microsoft Entra con Microsoft.Data.SqlClient.

SQL Server con autenticazione SQL

Usa il server, la porta, il database e il login per la tua istanza di SQL Server. Il seguente esempio è per un'istanza di sviluppo locale che non ha un certificato affidabile. Per PowerShell:

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

Per 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 Salta la validazione dei certificati del server. Usalo solo con un'istanza di sviluppo locale che non ha un certificato affidabile. Per istanze SQL Server condivise o di produzione, installare un certificato di cui il client si fida, utilizzare il nome del server su quel certificato e rimuovere TrustServerCertificate=true. Per altre informazioni, vedere Crittografia e convalida dei certificati in Microsoft.Data.SqlClient.

Se il tuo ambiente supporta l'autenticazione integrata di Windows o Kerberos, sostituisci User ID e Password con Integrated Security=true. Per i requisiti di configurazione, vedi SQL Server e autenticazione di Windows.

Aggiungi il codice

Sostituire il contenuto di Program.cs con questo codice:

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

Eseguire l'app

Eseguire l'app:

dotnet run

La prima volta che esegui l'app, la tabella è vuota e l'output appare così:

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)

I tuoi timestamp sono diversi. Ogni run successivo aggiunge due righe in più, così gli ID continuano dalla run precedente.

Se l'app non riesce a connettersi, stampa il numero di errore SQL, l'ID della connessione client, il messaggio di errore e il messaggio di eccezione interno, poi esce con il codice 3. Per errori comuni, vedi Troubleshoot.

Funzionamento del codice

  • OpenAsync, ExecuteNonQueryAsync, ExecuteScalarAsync, ExecuteReaderAsync, e ReadAsync ricevono lo stesso CancellationToken. Premi Ctrl+C per annullare il lavoro in corso.
  • Il comando insert viene creato una sola volta ed eseguito una volta per ogni messaggio. Cambia solo il valore del parametro.
  • I tipi e le dimensioni dei parametri corrispondono alle colonne della tabella. I parametri inviano valori separatamente dal testo SQL, il che impedisce a quei valori di modificare il comando e aiuta SQL Server a riutilizzare i piani di interrogazione.
  • OUTPUT INSERTED.Id restituisce il nuovo valore identità, quindi ExecuteScalarAsync restituisce l'ID senza una seconda interrogazione.
  • await using rilascia i comandi, il lettore e la connessione, anche quando si verifica un'eccezione. Rilasciando la connessione, questa viene restituita al pool di connessioni. La versione di .NET Framework utilizza blocchi using, perché questi tipi non implementano IAsyncDisposable in .NET Framework.
  • SqlException.Number identifica l'errore e ClientConnectionId ti permette di abbinare un fallimento del client ai log lato server. Per i fallimenti di connessione su Linux e macOS, la causa è spesso visibile solo in InnerException, come un fallimento di validazione del certificato dietro il generico error: 35 - An internal exception was caught.

Troubleshoot

Errore o sintomo Controlli da eseguire Ulteriori informazioni
The certificate chain was issued by an authority that is not trustedsu Windows. Su Linux e macOS, error: 35 - An internal exception was caught, seguito dall'eccezione interna Certificate failed chain validation con UntrustedRoot. Il certificato del server non è considerato attendibile dal client, oppure il nome del server nella stringa di connessione non corrisponde al certificato. Installa un certificato attendibile. Usa TrustServerCertificate=true solo con un'istanza di sviluppo locale. Crittografia e validazione dei certificati in Microsoft. Data.SqlClient
SQL error 18456 con Login failed for user Il nome utente, la password o il nome del database sono sbagliati, oppure l'account non ha accesso al database. Per Microsoft Entra ID, verifica che l'identità sia stata aggiunta come utente del database. Guida alla risoluzione dei problemi di SqlClient
A network-related or instance-specific error occurred con error: 26, error: 40, oppure The wait operation timed out. Su Linux e macOS, un timeout mostra SQL error 258 con error: 35, seguito dall'eccezione interna The connection attempt timed out. Il nome del server o la porta non è corretto, il server non accetta connessioni TCP remote o un firewall blocca la porta. Per Azure SQL, controlla le regole del firewall del server. Guida alla risoluzione dei problemi di SqlClient
System.ArgumentException: Cannot find an authentication provider for 'ActiveDirectoryDefault' La stringa di connessione utilizza una modalità di autenticazione Active Directory, ma il progetto non fa riferimento a Microsoft.Data.SqlClient.Extensions.Azure. Aggiungi il package con la stessa versione di Microsoft.Data.SqlClient. L'autenticazione Microsoft Entra passa a un pacchetto di estensione nella 7.0
CS0234: The type or namespace name 'Data' does not exist in the namespace 'Microsoft' Il progetto non fa riferimento al Microsoft.Data.SqlClient pacchetto. Esegui il dotnet add package comando dalla cartella che contiene il file del progetto. Installare, aggiornare e distribuire Microsoft. Data.SqlClient
Ripristina report NU1902 o NU1903 per un pacchetto transitivo Un pacchetto da cui il driver dipende ha un avviso pubblicato. Azioni quando vengono segnalati pacchetti con vulnerabilità note

Pulire le risorse

La tabella rimane nel tuo database dopo l'uscita dell'app. Se non hai intenzione di continuare con l'avvio rapido ASP.NET Core, che usa la stessa tabella, eliminala con qualsiasi strumento di query:

DROP TABLE IF EXISTS dbo.SqlClientQuickstart;

Poi elimina la cartella del progetto. Dalla cartella genitore, per PowerShell:

Remove-Item -Recurse -Force SqlClientQuickstart

Per Bash:

rm -rf SqlClientQuickstart

Cancella la variabile di ambiente così la stringa di connessione non rimane nella sessione della shell. Per PowerShell, esegui Remove-Item Env:\SQL_CONNECTION_STRING. Per Bash, esegui unset SQL_CONNECTION_STRING.

Usa il pattern in un'applicazione

Mantieni questi confini quando sposti il campione in un'API, un servizio, un'app desktop o un worker in background:

  • Carica le informazioni di connessione tramite il sistema di configurazione dell'app.
  • Apri una connessione per una breve unità di lavoro, quindi eliminala.
  • Passare un CancellationToken tramite le chiamate open, command e reader.
  • Imposta i timeout dei comandi in base all'operazione.
  • Usa parametri per ogni valore che proviene da fuori dall'istruzione SQL.
  • Registra SqlException.Number e ClientConnectionId senza registrare credenziali o token di accesso.
  • Aggiungi ritentativi solo per errori temporanei e solo quando è sicuro ripetere l'operazione.

Passaggi successivi