Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Použijte SqlBatch k odeslání uspořádané kolekce objektů SqlBatchCommand přes jedno otevřené připojení SqlConnection. Každý dávkový příkaz má svůj vlastní text příkazu, typ příkazu, parametry, chování příkazu a výsledek počtu ovlivněných řádků.
Použijte SqlBatch, když má aplikace odlišné příkazy, které chce posílat dohromady. Používejte jeden parametrizovaný SqlCommand, pokud je dotaz jedním příkazem nebo uloženou procedurou. Použijte SqlBulkCopy nebo tabulkový parametr pro velké sady řádků.
Příklady v tomto článku předpokládají, že otevřené připojení SqlConnection s názvem connection cílí na ukázkovou databázi AdventureWorks.
Příklady v C# vyžadují using Microsoft.Data.SqlClient;. Příklady, které používají SqlDbType nebo CommandBehavior také vyžadují using System.Data;. Příklady, které používají DbDataReader, vyžadují using System.Data.Common;.
Podpora verzí a platformy
Příklady jsou zaměřeny na Microsoft.Data.SqlClient 7.1.0. Vyberte verzi balíčku a cílový framework, které jsou pro vaši aplikaci podporovány v životním cyklu podpory Microsoft.Data.SqlClient.
SqlBatch pochází z DbBatch v moderním .NET. Microsoft.Data.SqlClient také zpřístupňuje SqlBatch v prostředcích svého balíčku pro .NET Framework a .NET Standard 2.0. Veřejné rozhraní API se může lišit podle cílového frameworku, proto sestavte aplikaci pro každý cíl, který distribuujete.
Vytvořit dávku
Vytvořte batch pro otevřené spojení a poté přidejte příkazy v pořadí vykonávání:
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 je výchozí hodnota. Nastavte dávkový příkaz na CommandType.StoredProcedure pro uloženou proceduru. Nastavení CommandType.TableDirect vyvolá ArgumentOutOfRangeException.
Přidání parametrů do dávkových příkazů
Parametry patří jednotlivci SqlBatchCommand. Stejný zástupný název ve dvou dávkových příkazech nesdílí stejnou hodnotu:
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();
Nastavte SQL typ každého parametru a příslušnou velikost, přesnost a měřítko z kontraktu databáze. Další informace naleznete v tématu Konfigurace parametrů.
Spustit příkazy měnící data
Použijte ExecuteNonQuery nebo ExecuteNonQueryAsync když batch změní data a nepotřebujete výsledkové řádky. Vrácená hodnota je celkový počet řádků ovlivněných, když jsou počty řádků dostupné. Po provedení každý příkaz hlásí RecordsAffected svůj vlastní počet.
Tento příklad vrátí zpět provedené změny:
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();
Přečtěte si více výsledků najednou
Použijte ExecuteReader nebo ExecuteReaderAsync když jakýkoli příkaz vrátí řádky. Čtenář zobrazuje výsledky v pořadí dávkových příkazů. Zavolejte NextResult nebo NextResultAsync dokud nevrátí false.
Příkaz může vytvořit žádnou sadu řádků, jednu sadu řádků nebo více sad řádků. Nepředpokládejte, že jedno volání NextResult odpovídá jednomu SqlBatchCommand.
Použít chování příkazu
Předejte CommandBehavior do ExecuteReader nebo ExecuteReaderAsync, když čtečka potřebuje sekvenční přístup nebo musí uzavřít spojení:
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();
}
Přetížení na úrovni dávky přijímají pouze CommandBehavior.Default, CommandBehavior.SequentialAccess, CommandBehavior.CloseConnection a jejich kombinace. Další platné hodnoty, jako SingleRow, KeyInfo a ArgumentOutOfRangeException, vyvolají SchemaOnly při předání přetížení na úrovni dávky. Přetížení chování na úrovni dávky jsou dostupná počínaje verzí Microsoft.Data.SqlClient 7.1.
Nastavte CommandBehavior u jednotlivých příkazů pro možnosti jako SingleRow, SchemaOnly a KeyInfo. Použijte přetížení na úrovni dávky pro SequentialAccess a CloseConnection.
Použijte transakci
SqlBatch nezajišťuje atomické provedení svých příkazů. Použijte explicitní transakci, když všechny příkazy musí být commitovány nebo vráceny zpět dohromady. Tento příklad provede vrácení změn, takže AdventureWorks zůstává beze změny:
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();
Zavolejte Commit místo Rollback pouze tehdy, když aplikace přijme celou dávku. Přiřadit transakci před vykonáním. Transakce i dávková operace musí používat stejné spojení. SqlClient nepřepisuje asynchronní transakční metody, takže BeginTransactionAsync, CommitAsync a RollbackAsync se dokončují synchronně. Další informace najdete v článku Použití metod transakcí SQL založených na úlohách.
Řešit časové limity, zrušení a chyby
Nastavte Timeout pro dávku v sekundách. Batch používá nastavení připojení Command Timeout, když nějaké nakonfigurujete. Jinak je výchozí doba 30 sekund. Hodnota 0 nemá časový limit a záporné hodnoty vyvolají ArgumentException. Předejte token zrušení metodě asynchronního spuštění, když volající potřebuje přestat čekat, nebo zavolejte Cancel. Zrušení proběhne v rámci možností. Operace může být dokončena dříve, než zrušení začne platit.
Když se provedení nepodaří, zachyťte SqlException a zkontrolujte každou položku v jeho Errors kolekci.
BatchCommand identifikuje příslušný SqlBatchCommand, pokud jsou tyto informace k dispozici:
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}");
}
Spouštění modulu Reader je postupné. Chyba z pozdějšího dávkového příkazu se může objevit, když Read nebo NextResult postoupí k tomuto příkazu, takže zpracujte čtečku uvnitř bloku try.
Nezaznamenávejte hodnoty parametrů, které obsahují přihlašovací údaje, tokeny nebo citlivá data. Pro chybová pole a informační zprávy viz Zvládání chyb a zpráv.