Connettiti a una sorgente dati con Microsoft. Data.SqlClient

SqlConnectionrappresenta una connessione logica a SQL Server, Azure SQL o un altro endpoint compatibile con SQL Server. L'apertura dell'oggetto acquisisce una connessione fisica dal pool di connessioni quando ce n'è una disponibile. Chiudendolo o smaltirlo restituisce quella connessione fisica al pool.

Usa oggetti SqlConnection a vita breve per le unità di lavoro. Non lasciare aperta una sola connessione globale per l'applicazione.

Costruire la configurazione della connessione

Carica una stringa di connessione dal sistema di configurazione dell'applicazione. Da usare SqlConnectionStringBuilder quando il codice deve validare o aggiungere impostazioni:

string configuredConnectionString =
    configuration.GetConnectionString("Orders")
    ?? throw new InvalidOperationException(
        "Connection string 'Orders' wasn't configured.");

var builder = new SqlConnectionStringBuilder(configuredConnectionString)
{
    ApplicationName = "Orders.Api",
};

Crea il SqlConnection da builder.ConnectionString. Non concatenare l'input dell'utente nella stringa. Per pattern di autenticazione, archiviazione sicura e sintassi, vedi Stringhe di connessione.

Aprire e disporre le connessioni

Chiama Open codice sincrono o OpenAsync codice asincrono. Apri una nuova connessione logica per ogni operazione indipendente:

public static async Task<string?> LoadOrderStatusAsync(
    string connectionString,
    int orderId,
    CancellationToken cancellationToken)
{
    await using var connection = new SqlConnection(connectionString);
    await connection.OpenAsync(cancellationToken);

    const string sql = """
        SELECT Status
        FROM Sales.Orders
        WHERE OrderId = @orderId;
        """;

    using var command =
        new SqlCommand(sql, connection) { CommandTimeout = 30 };
    command.Parameters.Add(
        new SqlParameter("@orderId", SqlDbType.Int) { Value = orderId });

    object? value =
        await command.ExecuteScalarAsync(cancellationToken);
    return value is null or DBNull ? null : (string)value;
}

L'istruzione await using elimina la connessione in caso di successo, errore o cancellazione. Con il pooling abilitato, lo smaltimento normalmente resetta e restituisce la connessione fisica invece di chiudere il socket di rete.

Eliminare i reader e i command prima della connessione che li contiene. Non affidarti alla raccolta dei rifiuti o a un finalizer per riportare le connessioni alla piscina.

Usare le API asincrone

Usa chiamate asincrone per il lavoro su database legato alla rete in server web, servizi, interfacce utente e lavoratori:

  • OpenAsync(cancellationToken)
  • ExecuteNonQueryAsync(cancellationToken)
  • ExecuteReaderAsync(cancellationToken)
  • ExecuteScalarAsync(cancellationToken)
  • ReadAsync(cancellationToken)

Non ne hai bisogno Asynchronous Processing=true. Microsoft. Data.SqlClient 4.0 e versioni successive non supportano quella parola chiave di stringa di connessione.

Non iniziare un'altra operazione su una connessione, un comando o un lettore prima che l'operazione asincrona attuale sia terminata.

Applica la cancellazione e i timeout

Propaga il CancellationToken del chiamante in ogni chiamata asincrona al database. La cancellazione chiede al fornitore di fermare il lavoro in sospeso, ma il completamento non è garantito immediato. Continua a usare timeout di connessione e di comando limitati.

Questi controlli hanno ambiti separati:

Controllo Scope
Connect Timeout Stabilire una connessione o attendere una connessione del pool
SqlCommand.CommandTimeout Esecuzione di un comando
CancellationToken Cancellazione richiesta dal chiamante di un'operazione asincrona

Un timeout o un annullamento non dimostrano che il server abbia annullato un'operazione. Utilizzare una transazione quando più modifiche devono effettuare un commit o tornare indietro come un'unica unità, e prendere decisioni di ritentativo basate sull'idempotenza e sull'esito della transazione.

Comprendere lo stato della connessione

La State proprietà restituisce una istantanea dall'enumerazione ConnectionState .

State Meaning
Closed La connessione logica non è aperta.
Connecting È in corso un'operazione aperta.
Open La connessione logica è aperta.

Non usare State come controllo dello stato prima di ogni comando. La rete può non funzionare dopo qualsiasi verifica. Esegui l'operazione e gestisci l'eccezione risultante.

Il conducente normalmente segnala transizioni da chiuso ad aperto e da aperto a chiuso. Non fare affidamento sull'osservazione di Executing, Fetching o Broken come fasi del ciclo di vita dell'applicazione.

L'evento StateChange riporta transizioni di stato. L'evento InfoMessage riporta messaggi informativi e avvisi del server che non diventano eccezioni. Usa questi eventi per diagnostica, non per coordinare il lavoro concorrente.

Non condividere una connessione contemporaneamente

SqlConnection, SqlCommand, SqlDataReader, e SqlTransaction non supportano l'uso concorrente da parte di più thread. Assegnare a ogni operazione concorrente la propria connessione e lasciare che il pool di connessione riutilizzi le connessioni fisiche.

I Multiple Active Result Set (MARS) consentono più lotti attivi su una sola connessione in scenari supportati. Non rende gli oggetti SqlClient thread-safe e aggiunge regole di sessione e transazione. Lascialo disabilitato a meno che un'operazione non ne abbia bisogno specificamente.

Non registrare un open SqlConnection come singleton nell'iniezione di dipendenza. Registra la stringa di connessione, un oggetto di opzioni immutabile o una funzione factory che crea una nuova connessione.

Usa le transazioni in modo consapevole

Una transazione locale è associata alla relativa connessione. Ogni comando nella transazione deve utilizzare quella connessione e impostarne Transaction la proprietà.

await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellationToken);

await using SqlTransaction transaction =
    (SqlTransaction)await connection.BeginTransactionAsync(cancellationToken);

using var command = new SqlCommand(sql, connection, transaction);
command.Parameters.Add(
    new SqlParameter("@value", SqlDbType.Int) { Value = value });
await command.ExecuteNonQueryAsync(cancellationToken);

await transaction.CommitAsync(cancellationToken);

Se l'operazione non riesce prima di CommitAsync, la chiusura della transazione ne esegue il rollback. Mantieni le transazioni brevi. Non fare chiamate di rete, interazioni con l'utente o calcoli non correlati mentre una transazione nel database contiene blocchi.

Quando System.Transactions.Transaction.Current è attivo, Open e OpenAsync vengono registrati automaticamente per impostazione predefinita. Impostare Enlist=false solo quando l'operazione deve restare all'esterno della transazione ambientale.

Misurare una connessione logica

Imposta StatisticsEnabled su true per raccogliere le statistiche del provider per un oggetto SqlConnection:

await using var connection = new SqlConnection(connectionString)
{
    StatisticsEnabled = true,
};

await connection.OpenAsync(cancellationToken);
connection.ResetStatistics();

using var command = new SqlCommand(sql, connection);
await command.ExecuteNonQueryAsync(cancellationToken);

System.Collections.IDictionary statistics =
    connection.RetrieveStatistics();
long roundTrips =
    Convert.ToInt64(statistics["ServerRoundtrips"]);

RetrieveStatistics restituisce una istantanea. ResetStatistics Avvia un nuovo confine di misura. Impostato StatisticsEnabled=false per smettere di riscuotere; i valori raccolti finora restano disponibili. Le statistiche sono per oggetto di connessione e aggiungono overhead, quindi abilitali per una diagnosi mirata invece che per ogni richiesta di produzione.

Per misurazioni di pool e connessione a livello di processo, utilizza i contatori diagnostici SqlClient.

Gestire gli errori di connessione

Intercetta SqlException in un punto di confine che possa registrare, tradurre o ritentare l’operazione dopo l’errore. Registrazione:

  • Number
  • State
  • Class
  • ClientConnectionId
  • Il nome dell'operazione e gli identificatori configurati di server e database

Non registrare la stringa di connessione, la password, il client secret o il token di accesso.

Elimina una connessione rotta. Il pool rimuove le connessioni fisiche non valide quando le rileva. Se una credenziale, un token, un certificato, un DNS target o un server cambiato, correggi la configurazione prima di riprovare.

Usa la logica di ritentazione limitata solo per i fallimenti transitori. Il ritentativo di apertura iniziale, il recupero di una connessione inattiva e il ritentativo del comando sono meccanismi diversi. Vedi logica dei tentativi configurabile.