Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Gebruik SqlBatch om een geordende collectie SqlBatchCommand objecten door één open SqlConnection te sturen. Elk batchcommando heeft zijn eigen commandotekst, commandotype, parameters, commandogedrag en het resultaat van het aantal beïnvloede rijen.
Gebruik SqlBatch wanneer een applicatie verschillende commando's heeft die hij samen wil sturen. Gebruik één geparametriseerd SqlCommand wanneer de taak één statement of stored procedure is. Gebruik SqlBulkCopy of een parameter met tabelwaarde voor grote rijsets.
De voorbeelden in dit artikel gaan ervan uit dat een open SqlConnection met de naam connection de AdventureWorks-voorbeelddatabase als doel heeft.
De C#-voorbeelden vereisen using Microsoft.Data.SqlClient;. Voorbeelden die gebruikmaken van SqlDbType of CommandBehavior, vereisen ook using System.Data;. Voorbeelden die DbDataReader gebruiken, vereisen using System.Data.Common;.
Versie- en platformondersteuning
De voorbeelden richten zich op Microsoft.Data.SqlClient 7.1.0. Selecteer een pakketversie en een doelframework die worden ondersteund door de Microsoft.Data.SqlClient support lifecycle voor uw applicatie.
SqlBatch is afgeleid van DbBatch op modern .NET. Microsoft.Data.SqlClient biedt ook SqlBatch in zijn .NET Framework- en .NET Standard 2.0-pakketassets. De publieke API kan per target framework verschillen, dus compileer de applicatie voor elk doel dat je levert.
Een batch maken
Maak een batch aan voor een open verbinding en voeg vervolgens commando's toe in uitvoeringsvolgorde:
using var batch = new SqlBatch(connection);
batch.BatchCommands.Add(new SqlBatchCommand("""
SELECT TOP (3) ProductID, Name
FROM Production.Product
ORDER BY ProductID;
"""));
batch.BatchCommands.Add(new SqlBatchCommand("""
SELECT TOP (3) SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader
ORDER BY SalesOrderID;
"""));
using DbDataReader reader = batch.ExecuteReader();
do
{
while (reader.Read())
{
Console.WriteLine($"{reader.GetValue(0)} | {reader.GetValue(1)}");
}
}
while (reader.NextResult());
CommandType.Text is de standaardwaarde. Stel een batchcommando in op CommandType.StoredProcedure voor een opgeslagen procedure. Het instellen van ArgumentOutOfRangeException veroorzaakt CommandType.TableDirect.
Voeg parameters toe aan batchcommando's
Parameters behoren tot een individu SqlBatchCommand. Dezelfde placeholdernaam in twee batchcommando's deelt niet dezelfde waarde:
using var batch = new SqlBatch(connection);
var products = new SqlBatchCommand("""
SELECT ProductID, Name
FROM Production.Product
WHERE ProductSubcategoryID = @id
ORDER BY ProductID;
""");
products.Parameters.Add("@id", SqlDbType.Int).Value = 2;
batch.BatchCommands.Add(products);
var orders = new SqlBatchCommand("""
SELECT SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader
WHERE SalesPersonID = @id
ORDER BY SalesOrderID;
""");
orders.Parameters.Add("@id", SqlDbType.Int).Value = 279;
batch.BatchCommands.Add(orders);
using DbDataReader reader = batch.ExecuteReader();
Stel het SQL-type en de toepasselijke grootte, precisie en schaal van elke parameter in vanuit het databasecontract. Zie Parameters configureren voor meer informatie.
Voer data-veranderende commando's uit
Gebruik ExecuteNonQuery of ExecuteNonQueryAsync wanneer de batch data verandert en je geen resultaatrijen meer nodig hebt. De teruggegeven waarde is het totaal aantal rijen dat wordt beïnvloed wanneer er aantallen rijen beschikbaar zijn. Na uitvoering rapporteert elk commando zijn eigen aantal.
Dit voorbeeld draait de wijzigingen terug:
using SqlTransaction transaction = connection.BeginTransaction();
using var batch = new SqlBatch(connection, transaction);
var firstUpdate = new SqlBatchCommand("""
UPDATE Sales.SalesOrderHeader
SET Status = @status
WHERE SalesOrderID = @salesOrderId;
""");
firstUpdate.Parameters.Add("@status", SqlDbType.TinyInt).Value = 2;
firstUpdate.Parameters.Add("@salesOrderId", SqlDbType.Int).Value = 43659;
batch.BatchCommands.Add(firstUpdate);
var secondUpdate = new SqlBatchCommand("""
UPDATE Sales.SalesOrderHeader
SET Status = @status
WHERE SalesOrderID = @salesOrderId;
""");
secondUpdate.Parameters.Add("@status", SqlDbType.TinyInt).Value = 2;
secondUpdate.Parameters.Add("@salesOrderId", SqlDbType.Int).Value = 43660;
batch.BatchCommands.Add(secondUpdate);
int totalRows = batch.ExecuteNonQuery();
Console.WriteLine($"Total rows: {totalRows}");
foreach (SqlBatchCommand command in batch.BatchCommands)
{
Console.WriteLine(command.RecordsAffected);
}
transaction.Rollback();
Lees meerdere resultaten
Gebruik ExecuteReader of ExecuteReaderAsync wanneer een commando rijen teruggeeft. De lezer stelt resultaten beschikbaar in de batchvolgorde van opdrachten. Bel NextResult of NextResultAsync totdat het false retourneert.
Een commando kan geen rijset, één rijset of meerdere rijsets produceren. Ga er niet van uit dat één NextResult call overeenkomt met één SqlBatchCommand.
Gedrag van opdrachten gebruiken
Geef een batchniveau-CommandBehavior door aan ExecuteReader of ExecuteReaderAsync wanneer de reader sequentiële toegang nodig heeft of de verbinding moet sluiten:
using var batch = new SqlBatch(connection);
batch.BatchCommands.Add(new SqlBatchCommand("""
SELECT DocumentSummary
FROM Production.Document
WHERE DocumentSummary IS NOT NULL;
"""));
using DbDataReader reader =
batch.ExecuteReader(CommandBehavior.SequentialAccess);
char[] buffer = new char[4096];
while (reader.Read())
{
using TextReader summary = reader.GetTextReader(0);
int count;
while ((count = summary.Read(buffer, 0, buffer.Length)) > 0)
{
Console.Out.Write(buffer, 0, count);
}
Console.WriteLine();
}
De batch-niveau overloads accepteren alleen CommandBehavior.Default, CommandBehavior.SequentialAccess, CommandBehavior.CloseConnection, en combinaties van die waarden. Andere geldige waarden, zoals SingleRow, KeyInfo en ArgumentOutOfRangeException, werpen SchemaOnly op wanneer ze worden doorgegeven aan een overload op batchniveau. De batch-niveau gedragsoverloads zijn beschikbaar vanaf Microsoft. Data.SqlClient 7.1.
Stel CommandBehavior in voor een afzonderlijke opdracht voor opties zoals SingleRow, SchemaOnly en KeyInfo. Gebruik de batch-niveau overload voor SequentialAccess en CloseConnection.
Een transactie gebruiken
SqlBatch maakt zijn commando's niet atomisch. Gebruik een expliciete transactie wanneer alle commando's samen moeten committen of terugrollen. Dit voorbeeld wordt teruggedraaid zodat AdventureWorks ongewijzigd blijft:
using SqlTransaction transaction = connection.BeginTransaction();
using var batch = new SqlBatch(connection, transaction);
batch.BatchCommands.Add(new SqlBatchCommand("""
UPDATE Sales.SalesOrderHeader
SET Status = 2
WHERE SalesOrderID = 43659;
"""));
batch.BatchCommands.Add(new SqlBatchCommand("""
UPDATE Sales.SalesOrderHeader
SET Status = 2
WHERE SalesOrderID = 43660;
"""));
batch.ExecuteNonQuery();
transaction.Rollback();
Bel Commit in plaats van Rollback alleen wanneer de applicatie de volledige batch accepteert. Wijs de transactie toe vóór uitvoering. De transactie en batch moeten dezelfde verbinding gebruiken. SqlClient overschrijft de asynchrone transactiemethoden niet, dus BeginTransactionAsync, CommitAsync en RollbackAsync voltooien synchroon. Voor meer informatie, zie Gebruik taakgebaseerde SQL-transactiemethoden.
Omgaan met time-outs, annuleren en fouten
Stel Timeout in seconden in voor de batch. De batch gebruikt de Command Timeout instelling van de verbinding wanneer je er een instelt. Zo niet, dan is de standaardwaarde 30 seconden. Een waarde van 0 heeft geen tijdslimiet en negatieve waarden genereren ArgumentException. Geef een annuleringstoken door aan een asynchrone uitvoeringsmethode wanneer de aanroeper moet stoppen met wachten, of roep Cancel aan. Annuleren gebeurt op basis van best effort. De bewerking kan worden afgerond voordat de annulering van kracht wordt.
Wanneer de uitvoering faalt, vang SqlException en inspecteer dan elk item in de Errors collectie.
BatchCommand Identificeert de bijbehorende SqlBatchCommand wanneer die informatie beschikbaar is:
using var batch = new SqlBatch(connection);
batch.BatchCommands.Add(new SqlBatchCommand(
"SELECT TOP (1) ProductID FROM Production.Product;"));
batch.BatchCommands.Add(new SqlBatchCommand("SELECT 1 / 0;"));
try
{
using DbDataReader reader = batch.ExecuteReader();
do
{
while (reader.Read())
{
Console.WriteLine(reader.GetValue(0));
}
}
while (reader.NextResult());
}
catch (SqlException exception)
{
Console.WriteLine(
exception.BatchCommand is null
? "The batch failed."
: $"Failed command: {exception.BatchCommand.CommandText}");
}
De uitvoering van de Reader is incrementeel. Een fout uit een later batchcommando kan optreden wanneer Read of NextResult bij dat commando aankomt, dus verwerk de lezer binnen het try-blok.
Log geen parameterwaarden die inloggegevens, tokens of gevoelige gegevens bevatten. Voor foutvelden en informatieve berichten, zie Fouten en berichten behandelen.