Een opdracht uitvoeren

Gebruik SqlCommand om Transact-SQL (T-SQL) statements of opgeslagen procedures uit te voeren. Een commando vereist een open SqlConnection. Verwijder de opdracht na gebruik en verwijder de reader voordat je de verbinding opnieuw gebruikt.

De voorbeelden in dit artikel gaan ervan uit dat een open SqlConnection met de naam connection gericht is op de AdventureWorks-voorbeelddatabase.

De C#-voorbeelden vereisen using Microsoft.Data.SqlClient;. Voorbeelden die SqlDbType, CommandType of CommandBehavior gebruiken, vereisen ook using System.Data;.

Voor verbindingsopzet, authenticatie en encryptie, zie Verbindingsstrings en Versleuteling en certificaatvalidatie.

Kies een uitvoeringsmethode

Kies de methode die overeenkomt met het verwachte resultaat:

Method Wanneer gebruiken Result
ExecuteNonQuery Het commando wijzigt gegevens of schema. Het aantal beïnvloede rijen. -1 kan optreden wanneer er geen telling beschikbaar is, ook wanneer SET NOCOUNT ON tellingen onderdrukt.
ExecuteScalar Je hebt één waarde nodig. De eerste kolom van de eerste rij, of null wanneer het resultaat geen rijen heeft. Een database NULL wordt geretourneerd als Value.
ExecuteReader Je hebt rijen, meerdere resultaatsets of schema's nodig. A SqlDataReader.
ExecuteXmlReader Het commando retourneert XML in de vorm die vereist is door ExecuteXmlReader. Een XmlReader.

Elke methode heeft een taakgebaseerde asynchrone tegenhanger. Geef een CancellationToken door wanneer de aanroeper moet stoppen met wachten. Voor annulerings- en timeout-gedrag, zie Asynchrone programmering.

Voer een tekstcommando uit

CommandType.Text is de standaardwaarde. Plaats de statement in CommandText en laat waarden door parameters gaan:

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

Voor parametertypes, groottes, nullwaarden en richtingen, zie Parameters configureren. Voeg onbetrouwbare waarden niet samen in CommandText.

Een opgeslagen procedure uitvoeren

Stel CommandType.StoredProcedure in en gebruik de schema-gekwalificeerde procedurenaam:

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 ondersteunt CommandType.Text en CommandType.StoredProcedure. Het instellen van ArgumentOutOfRangeException geeft CommandType.TableDirect.

Controleer wat elke methode oplevert

Gebruik ExecuteScalar wanneer je één waarde nodig hebt:

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 geeft terug null wanneer het resultaat geen rijen heeft en DBNull.Value wanneer de eerste waarde een database NULLis .

Gebruik ExecuteNonQuery voor data-veranderende statements. Dit voorbeeld draait de wijziging terug zodat AdventureWorks ongewijzigd blijft:

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 onderdrukt het aantal getroffen rijen, zodat ExecuteNonQuery-1 kan retourneren, zelfs wanneer een statement gegevens verandert.

Gebruik ExecuteXmlReader voor een FOR XML resultaat:

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());

Gebruik een lokale transactie

Wanneer een verbinding een actieve lokale SqlTransaction heeft, wijs die transactie toe aan elk commando dat op de verbinding wordt uitgevoerd. Dit voorbeeld draait de wijziging terug zodat AdventureWorks ongewijzigd blijft:

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();

Bel Commit in plaats van Rollback alleen wanneer de applicatie de volledige transactie accepteert. Een commando dat niet naar de actieve transactie verwijst, gooit InvalidOperationException. De uitvoering faalt ook als de transactie bij een andere verbinding hoort. Voor transactiegrenzen en rollback, zie Lokale transacties.

Stel een commando-timeout in

CommandTimeout beperkt de uitvoering van commando's en de cumulatieve wachttijden voor het lezen van het netwerk in seconden. Een commando gebruikt de Command Timeout instelling van de verbinding wanneer er een is geconfigureerd. Anders is de standaardwaarde 30 seconden. Een waarde van 0 heeft geen tijdslimiet. Negatieve waarden genereren ArgumentException.

Wanneer de timeout afloopt, geeft het commando SqlException met Number ingesteld op -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 Beperkt het opzetten van verbindingen en de wachttijden voor de pool. CommandTimeout begint nadat de uitvoering van het commando begint. Voor meer informatie, zie Verbindingsopties.

Gebruik samen een eindige timeout en een cancellation token. De timeout stelt een limiet vast aan de database-operatie. Het annuleren van de token kan de controle teruggeven aan de aanroeper voordat de timeout afloopt. Ga er niet van uit dat annuleren en time-out dezelfde uitzondering opleveren.

Opnieuw gebruiken en opdrachten voorbereiden

Voeg één keer een parameter toe en verander daarna de waarde ervan nadat elke uitvoering is afgerond:

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

Bel Prepare alleen wanneer de metingen het rechtvaardigen. Prepare bereidt geen opgeslagen procedures of tekstcommando's zonder parameters voor. Voor geparametriseerde tekst stel je volledige metadata zoals Size, Scale en Prepare op elke parameter in voordat je Precision aanroept.

Probleemoplossingsopdrachten

Vang SqlException op rond de databaseoperatie en inspecteer de Errors-verzameling ervan wanneer de server meer dan één foutmelding geeft. Voor commandofouten, waarschuwingen en informatieve berichten, zie Fouten en berichten afhandelen.

Gebruik diagnostische tellers, eventbrontracering en de SqlClient probleemoplossingsgids wanneer een fout meer context vereist. Pas configureerbare herprobeerlogica alleen toe wanneer het herhalen van het commando veilig is.