Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Use SqlCommand para executar instruções Transact-SQL (T-SQL) ou procedimentos armazenados. Um comando precisa de um arquivo aberto SqlConnection. Descarte o comando após o uso e descarte qualquer reader antes de reutilizar a conexão.
Os exemplos deste artigo presumem que uma conexão connection aberta chamada SqlConnection tem como destino o banco de dados de exemplo AdventureWorks.
Os exemplos de C# requerem using Microsoft.Data.SqlClient;. Exemplos que usam SqlDbType, CommandType, ou CommandBehavior também requerem using System.Data;.
Para configuração, autenticação e criptografia de conexão, veja Strings de conexão e Criptografia e validação de certificados.
Escolha um método de execução
Escolha o método que corresponde ao resultado esperado:
| Método | Usar quando | Resultado |
|---|---|---|
| ExecuteNonQuery | O comando altera dados ou esquema. | O número de linhas afetadas.
-1 pode ocorrer quando não há contagem disponível, inclusive quando SET NOCOUNT ON suprime contagens. |
| ExecuteScalar | Você precisa de um valor. | A primeira coluna da primeira linha, ou null quando o resultado não tem linhas. Um banco de dados NULL é retornado como Value. |
| ExecuteReader | Você precisa de linhas, múltiplos conjuntos de resultados ou esquema. | Um SqlDataReader. |
| ExecuteXmlReader | O comando retorna XML na forma exigida por ExecuteXmlReader. |
Um XmlReader. |
Cada método possui um equivalente assíncrono baseado em tarefas. Passe a CancellationToken quando o chamador precisar parar de esperar. Para comportamento de cancelamento e timeout, veja Programação assíncrona.
Executar um comando de texto
CommandType.Text é o padrão. Coloque a instrução em CommandText e passe valores pelos parâmetros:
const string sql = """
SELECT ProductID, Name, ListPrice
FROM Production.Product
WHERE ProductSubcategoryID = @subcategoryId
ORDER BY ListPrice DESC;
""";
using var command = new SqlCommand(sql, connection);
command.Parameters.Add("@subcategoryId", SqlDbType.Int).Value = 2;
using SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(
$"{reader.GetInt32(0)} | {reader.GetString(1)} | {reader.GetDecimal(2):C}");
}
Para tipos de parâmetros, tamanhos, valores nulos e direções, veja Configurar parâmetros. Não concatene valores não confiáveis a CommandText.
Executar um procedimento armazenado
Defina CommandType.StoredProcedure e use o nome do procedimento qualificado pelo esquema:
using var command = new SqlCommand(
"dbo.uspGetEmployeeManagers",
connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(
"@BusinessEntityID",
SqlDbType.Int).Value = 6;
using SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(
$"{reader.GetString(2)} {reader.GetString(3)}");
}
Microsoft. Data.SqlClient suporta CommandType.Text e CommandType.StoredProcedure. Definir CommandType.TableDirect gera ArgumentOutOfRangeException.
Verifique o que cada método retorna
Use ExecuteScalar quando você precisa de um valor:
using var command = new SqlCommand(
"SELECT COUNT(*) FROM Production.Product WHERE SellEndDate IS NULL;",
connection);
int currentProductCount = (int)command.ExecuteScalar()!;
Console.WriteLine($"Current products: {currentProductCount}");
ExecuteScalar retorna null quando o resultado não tem linhas e DBNull.Value quando o primeiro valor é um valor de banco de dados NULL.
Use ExecuteNonQuery para instruções que alteram dados. Este exemplo reverte sua alteração para que o AdventureWorks permaneça inalterado:
using SqlTransaction transaction = connection.BeginTransaction();
using var command = new SqlCommand("""
UPDATE Sales.SalesOrderHeader
SET Status = @status
WHERE SalesOrderID = @salesOrderId;
""", connection, transaction);
command.Parameters.Add("@status", SqlDbType.TinyInt).Value = 2;
command.Parameters.Add("@salesOrderId", SqlDbType.Int).Value = 43659;
int rowsAffected = command.ExecuteNonQuery();
Console.WriteLine($"Rows affected: {rowsAffected}");
transaction.Rollback();
SET NOCOUNT ON suprime a contagens de linhas afetadas, então ExecuteNonQuery pode retornar -1 mesmo quando uma instrução altera os dados.
Use ExecuteXmlReader para um FOR XML resultado:
using var command = new SqlCommand("""
SELECT TOP (3) ProductID, Name
FROM Production.Product
ORDER BY ProductID
FOR XML PATH('Product'), ROOT('Products');
""", connection);
using System.Xml.XmlReader reader = command.ExecuteXmlReader();
reader.MoveToContent();
Console.WriteLine(reader.ReadOuterXml());
Use uma transação local
Quando uma conexão tem uma transação local ativa SqlTransaction, atribua essa transação a cada comando executado na conexão. Este exemplo reverte sua alteração para que o AdventureWorks permaneça inalterado:
using SqlTransaction transaction = connection.BeginTransaction();
using var command = new SqlCommand("""
UPDATE Sales.SalesOrderHeader
SET Status = @status
WHERE SalesOrderID = @salesOrderId;
""", connection, transaction);
command.Parameters.Add("@status", SqlDbType.TinyInt).Value = 2;
command.Parameters.Add("@salesOrderId", SqlDbType.Int).Value = 43659;
command.ExecuteNonQuery();
transaction.Rollback();
Ligue Commit em vez de Rollback apenas quando a aplicação aceitar a transação completa. Um comando que não faz referência à transação ativa lança InvalidOperationException. A execução também falha se a transação pertencer a outra conexão. Para limites de transação e rollback, veja Transações Locais.
Defina um tempo limite de comando
CommandTimeout limita a execução de comandos e as esperas cumulativas de leitura de rede em segundos. Um comando usa a configuração da Command Timeout conexão quando uma está configurada. Caso contrário, o padrão é 30 segundos. Um valor de 0 não tem limite de tempo. Valores negativos geram ArgumentException.
Quando o tempo limite expira, o comando lança SqlException com Number definido para -2:
using var command = new SqlCommand(
"WAITFOR DELAY '00:00:05';",
connection)
{
CommandTimeout = 1
};
try
{
command.ExecuteNonQuery();
}
catch (SqlException exception) when (exception.Number == -2)
{
Console.WriteLine("The command timed out.");
}
Connect Timeout limita o estabelecimento de conexão e as esperas no pool de conexões.
CommandTimeout começa após o início da execução do comando. Para mais informações, veja Opções de conexão.
Use um tempo limite finito e um token de cancelamento juntos. O timeout estabelece um limite para a operação do banco de dados. Cancelar o token pode devolver o controle ao chamador antes do timeout expirar. Não presuma que cancelamento e timeout produzem a mesma exceção.
Reutilizar e preparar comandos
Adicione um parâmetro uma vez e então mude seu valor após o término de cada execução:
using var command = new SqlCommand("""
SELECT TOP (1) Name, ListPrice
FROM Production.Product
WHERE ProductSubcategoryID = @subcategoryId
ORDER BY ListPrice DESC;
""", connection);
SqlParameter subcategoryId = command.Parameters.Add(
"@subcategoryId",
SqlDbType.Int);
foreach (int id in new[] { 1, 2, 3 })
{
subcategoryId.Value = id;
using SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
Console.WriteLine($"{id}: {reader.GetString(0)}");
}
}
Chame Prepare apenas quando as medições justificarem.
Prepare não prepara procedimentos armazenados ou comandos de texto sem parâmetros. Para texto parametrizado, defina metadados completos como Size, Scale e Prepare em cada parâmetro antes de chamar Precision.
Comandos de solução de problemas
Capture SqlException durante a operação do banco de dados e inspecione sua coleção Errors quando o servidor devolver mais de um erro. Para erros de comando, avisos e mensagens informativas, consulte Tratar erros e mensagens.
Use contadores de diagnóstico, rastreamento de fontes de eventos e o guia de solução de problemas do SqlClient quando um erro exigir mais contexto. Aplique lógica de retentativa configurável somente quando repetir o comando for seguro.