Conecte-se a uma fonte de dados com a Microsoft. Data.SqlClient

SqlConnectionrepresenta uma conexão lógica com o SQL Server, SQL do Azure ou outro endpoint compatível com SQL Server suportado. Ao abrir o objeto, obtém-se uma conexão física do pool de conexões quando houver uma disponível. Fechar ou descartá-lo retorna essa conexão física ao pool.

Use objetos de curta duração SqlConnection para unidades de trabalho. Não mantenha uma conexão global aberta para a aplicação.

Construa a configuração da conexão

Carregue uma cadeia de conexão do sistema de configuração da aplicação. Use SqlConnectionStringBuilder quando o código precisar validar ou adicionar configurações:

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

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

Crie o SqlConnection a partir de builder.ConnectionString. Não concatene a entrada do usuário na string. Para padrões de autenticação, armazenamento seguro e sintaxe, veja Strings de conexão.

Abrir e fechar conexões

Chame Open em código síncrono ou OpenAsync em código assíncrono. Abra uma nova conexão lógica para cada operação independente:

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

A await using instrução elimina a conexão em caso de sucesso, erro ou cancelamento. Com o pooling ativado, o descarte normalmente reinicia e retorna a conexão física em vez de fechar seu soquete de rede.

Descarte os leitores e os comandos antes da conexão à qual estão associados. Não dependa do coletor de lixo nem de um finalizador para devolver as conexões ao pool.

Usar APIs assíncronas

Use chamadas assíncronas para trabalho de banco de dados vinculado à rede em servidores web, serviços, interfaces de usuário e trabalhadores:

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

Você não precisa de Asynchronous Processing=true. Microsoft. Data.SqlClient 4.0 e versões posteriores não suportam essa palavra-chave de cadeia de conexão.

Não inicie outra operação em uma conexão, comando ou leitor antes que a operação assíncrona atual termine.

Aplicar cancelamento e tempos limite

Passe o CancellationToken do chamador em todas as chamadas assíncronas ao banco de dados. O cancelamento solicita ao provedor que interrompa o trabalho pendente, mas não há garantia de que a conclusão seja imediata. Continue usando tempos limite de conexão e de comando.

Esses controles possuem escopos separados:

Controle Scope
Connect Timeout Estabelecimento de conexão ou espera de uma conexão agrupada
SqlCommand.CommandTimeout Execução de um comando
CancellationToken Cancelamento solicitado pelo chamador de uma operação assíncrona

Um tempo limite ou cancelamento não prova que o servidor reverteu uma operação. Use uma transação quando várias alterações precisarem ser confirmadas ou revertidas como uma única unidade, e tome decisões sobre nova tentativa com base na idempotência da operação e no resultado da transação.

Entenda o estado da conexão

A State propriedade retorna um snapshot da ConnectionState enumeração.

State Meaning
Closed A conexão lógica não está aberta.
Connecting Uma operação aberta está em andamento.
Open A conexão lógica está aberta.

Não use State como checagem de saúde antes de cada comando. A rede pode falhar após qualquer verificação. Execute a operação e trate da exceção resultante.

O controlador normalmente indica transições de fechado para aberto e de aberto para fechado. Não dependa de tratar Executing, Fetching ou Broken como fases do ciclo de vida do aplicativo.

O StateChange evento relata transições de estado. O evento InfoMessage relata mensagens informativas e avisos do servidor que não chegam a se tornar exceções. Use esses eventos para diagnósticos, não para coordenar trabalhos simultâneos.

Não compartilhe uma conexão ao mesmo tempo

SqlConnection, SqlCommand, SqlDataReader, e SqlTransaction não suportam uso simultâneo por múltiplas threads. Dê a cada operação concorrente sua própria conexão e permita que o pool de conexões reutilize as conexões físicas.

Múltiplos Conjuntos de Resultados Ativos (MARS) permitem múltiplos lotes ativos em uma única conexão em cenários suportados. Isso não torna os objetos SqlClient seguros para threads, e adiciona regras de sessão e transação. Deixe-o desativado, a menos que uma operação precise especificamente.

Não registre um genérico aberto SqlConnection como singleton na injeção de dependências. Registre a cadeia de conexão, um objeto de opções imutável ou uma fábrica que cria uma nova conexão.

Use transações com critério

Uma transação local pertence à sua conexão. Todo comando na transação deve usar essa conexão e definir sua Transaction propriedade.

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 a operação falhar antes de CommitAsync, o descarte da transação a reverte. Mantenha as transações curtas. Não faça chamadas de rede, interação com usuários ou cálculos não relacionados enquanto uma transação de banco de dados mantém bloqueios.

Quando System.Transactions.Transaction.Current estiver ativado, Open e OpenAsync serão automaticamente inscritos por padrão. Definido Enlist=false apenas quando a operação deve permanecer fora da transação ambiente.

Medir uma conexão lógica

Defina StatisticsEnabled como true para coletar estatísticas do provedor para um objeto 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 retorna um snapshot. ResetStatistics Inicia uma nova fronteira de medição. Defina StatisticsEnabled=false para interromper a coleta; os valores coletados até o momento continuam disponíveis. As estatísticas são específicas de cada objeto de conexão e geram sobrecarga; portanto, ative-as para diagnósticos direcionados em vez de ativá-las em todas as solicitações de produção.

Para medições de pools e conexões de todo o processo, utilize contadores de diagnóstico do SqlClient.

Tratar falhas de conexão

Prenda SqlException em um limite que possa registrar, traduzir ou tentar novamente a falha. Registro:

  • Number
  • State
  • Class
  • ClientConnectionId
  • O nome da operação e identificadores de servidor e banco de dados configurados

Não registre a cadeia de conexão, a senha, o segredo do cliente nem o token de acesso.

Elimine uma conexão quebrada. O pool remove conexões físicas inválidas quando as detecta. Se uma credencial, token, certificado, destino DNS ou servidor for alterado, corrija a configuração antes de tentar novamente.

Use lógica de repetição limitada apenas para falhas transitórias. A nova tentativa na abertura inicial, a recuperação de conexão ociosa e a nova tentativa de comando são mecanismos diferentes. Veja Lógica de retentativas configurável.