Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Verwenden Sie SqlBatch, um eine geordnete Sammlung von SqlBatchCommand Objekten durch ein offenes SqlConnection zu schicken. Jeder Batch-Befehl hat seinen eigenen Befehlstext, Befehlstyp, Parameter, Befehlsverhalten und das Ergebnis der betroffenen Zeilen.
Verwenden Sie SqlBatch, wenn eine Anwendung unterschiedliche Befehle zusammen senden möchte. Verwenden Sie einen parametrisierten SqlCommand, wenn der Vorgang eine Anweisung oder eine gespeicherte Prozedur ist. Verwenden Sie SqlBulkCopy oder einen tabellenwertigen Parameter für große Zeilensätze.
In den Beispielen in diesem Artikel wird vorausgesetzt, dass eine geöffnete SqlConnection mit dem Namen connection auf die AdventureWorks-Beispieldatenbank abzielt.
Die C#-Beispiele erfordern using Microsoft.Data.SqlClient;. Beispiele, die SqlDbType oder CommandBehavior verwenden, erfordern auch using System.Data;. Beispiele, die DbDataReader verwenden, erfordern using System.Data.Common;.
Unterstützung für Versionen und Plattformen
Die Beispiele richten sich an Microsoft.Data.SqlClient 7.1.0. Wählen Sie eine Paketversion und ein Ziel-Framework aus, die der Supportlebenszyklus von Microsoft.Data.SqlClient für Ihre Anwendung unterstützt.
SqlBatch leitet sich unter modernem .NET von DbBatch ab. Microsoft. Data.SqlClient stellt SqlBatch außerdem in seinem .NET Framework und .NET Standard 2.0 Paket-Assets bereit. Die öffentliche API-Oberfläche kann je nach Zielframework unterschiedlich sein, daher kompiliere die Anwendung für jedes Ziel, das du auslieferst.
Batch erstellen
Erstelle einen Batch für eine offene Verbindung und füge dann Befehle in der Ausführungsreihenfolge hinzu:
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 ist der Standardwert. Legen Sie einen Batchbefehl für eine gespeicherte Prozedur auf CommandType.StoredProcedure fest. Das Setzen von CommandType.TableDirect löst ArgumentOutOfRangeException aus.
Fügen Sie Parameter zu Batch-Befehlen hinzu
Parameter gehören zu einem einzelnen SqlBatchCommand. Der gleiche Platzhaltername in zwei Batch-Befehlen haben keinen gemeinsamen Wert:
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();
Legen Sie den SQL-Typ jedes Parameters sowie die anwendbare Größe, Präzision und Skalierung aus dem Datenbankvertrag fest. Weitere Informationen finden Sie unter Konfigurieren von Parametern.
Datenändernde Befehle ausführen
Verwenden Sie ExecuteNonQuery oder ExecuteNonQueryAsync, wenn der Batch die Daten ändert und Sie keine Ergebniszeilen benötigen. Der zurückgegebene Wert ist die Gesamtzahl der betroffenen Zeilen, wenn Zeilenzählungen verfügbar sind. Nach der Ausführung meldet jeder Befehl in RecordsAffected seine eigene Anzahl.
Dieses Beispiel macht seine Änderungen rückgängig:
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();
Mehrere Ergebnisse lesen
Verwenden Sie ExecuteReader oder ExecuteReaderAsync, wenn ein Befehl Zeilen zurückgibt. Der Leser gibt die Ergebnisse in der Reihenfolge der Batch-Befehle aus. Ruf NextResult an oder NextResultAsync, bis false zurückgegeben wird.
Ein Befehl kann keine Zeilenmenge, eine Zeilenmenge oder mehrere Zeilenmengen erzeugen. Gehen Sie nicht davon aus, dass ein Aufruf NextResult einem SqlBatchCommand entspricht.
Befehlsverhalten verwenden
Übergeben Sie ein CommandBehavior auf Batch-Ebene an ExecuteReader oder ExecuteReaderAsync, wenn der Leser sequenziellen Zugriff benötigt oder die Verbindung schließen muss:
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();
}
Die Batch-Überladungen akzeptieren nur CommandBehavior.Default, CommandBehavior.SequentialAccess, CommandBehavior.CloseConnection und Kombinationen dieser Werte. Andere gültige Werte wie SingleRow, KeyInfo und ArgumentOutOfRangeException lösen SchemaOnly aus, wenn sie an eine Überladung auf Batchebene übergeben werden. Die Verhaltensüberladungen auf Batchebene sind ab Microsoft.Data.SqlClient 7.1 verfügbar.
Legen Sie CommandBehavior für einen einzelnen Befehl für Optionen wie SingleRow, SchemaOnly und KeyInfo fest. Verwenden Sie den Batch-Level-Overload für SequentialAccess und CloseConnection.
Eine Transaktion verwenden
SqlBatch führt seine Befehle nicht atomar aus. Verwenden Sie eine explizite Transaktion, bei der alle Befehle gemeinsam committen oder zurückrollen müssen. Dieses Beispiel rollt zurück, sodass AdventureWorks unverändert bleibt:
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();
Rufen Sie Commit anstelle von Rollback nur auf, wenn die Anwendung den vollständigen Batch akzeptiert. Weise die Transaktion vor der Ausführung zu. Die Transaktion und der Batch müssen dieselbe Verbindung verwenden. SqlClient überschreibt die asynchronen Transaktionsmethoden nicht, also werden BeginTransactionAsync, CommitAsync und RollbackAsync synchron abgeschlossen. Weitere Informationen finden Sie unter Aufgabenbasierte SQL-Transaktionsmethoden verwenden.
Bewältigen Sie Zeitüberschreitungen, Abbrüche und Fehler
Timeout für die Charge in Sekunden einstellen. Der Batch verwendet die Command Timeout Einstellung der Verbindung, wenn du eine konfigurierst. Ansonsten sind standardmäßig 30 Sekunden eingestellt. Ein Wert von 0 hat keine Zeitbegrenzung, und negative Werte werfen ArgumentException. Geben Sie ein Abbruchtoken an eine asynchrone Ausführungsmethode weiter, wenn der Anrufer das Warten beenden muss oder Cancel aufruft. Stornierungen erfolgen nach bestem Bemühen. Die Operation könnte abgeschlossen werden, bevor der Abbruch wirksam wird.
Wenn die Ausführung fehlschlägt, fangen Sie SqlException ab und inspizieren Sie jedes Element in seiner Errors Sammlung.
BatchCommand identifiziert das zugehörige SqlBatchCommand, wenn diese Information verfügbar ist:
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}");
}
Die Ausführung des Lesers erfolgt inkrementell. Ein Fehler aus einem späteren Batch-Befehl kann auftreten, wenn Read oder NextResult zu diesem Befehl gelangt, daher verarbeiten Sie den Reader im try-Block.
Protokolliere keine Parameterwerte, die Zugangsdaten, Token oder sensible Daten enthalten. Für Fehlerfelder und Informationsnachrichten siehe Mit Fehlern und Meldungen umgehen.