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.
Pomocí SqlCommand můžete provádět příkazy Transact-SQL (T-SQL) nebo uložené procedury. Příkaz potřebuje otevřený SqlConnection. Po použití příkaz zlikvidujte a před opětovným použitím připojení zlikvidujte objekt reader.
Příklady v tomto článku předpokládají, že otevřené připojení SqlConnection s názvem connection odkazuje na ukázkovou databázi AdventureWorks.
Příklady v C# vyžadují using Microsoft.Data.SqlClient;. Příklady, které používají SqlDbType, CommandType, nebo CommandBehavior také vyžadují using System.Data;.
Pro nastavení spojení, autentizaci a šifrování viz Připojovací řetězce a Šifrování a ověřování certifikátů.
Vyberte způsob provádění
Vyberte metodu, která odpovídá očekávanému výsledku:
| Metoda | Použít, když | Výsledek |
|---|---|---|
| ExecuteNonQuery | Příkaz mění data nebo schéma. | Počet ovlivněných řádků
-1 může nastat, když není k dispozici žádný počet, včetně případů, kdy SET NOCOUNT ON potlačuje počty. |
| ExecuteScalar | Potřebujete jednu hodnotu. | První sloupec prvního řádku, nebo null když výsledek nemá žádné řádky. Databáze NULL se vrací jako Value. |
| ExecuteReader | Potřebujete řádky, více sad výsledků nebo schéma. | Nějaké SqlDataReader. |
| ExecuteXmlReader | Příkaz vrací XML ve tvaru požadovaném prvkem ExecuteXmlReader. |
Nějaký XmlReader. |
Každá metoda má asynchronní protějšek založený na úkolech. Předejte CancellationToken, když volající potřebuje přestat čekat. Pro chování při rušení a časovém limitu viz Asynchronní programování.
Spustit textový příkaz
CommandType.Text je výchozí hodnota. Vložte instrukci do CommandText a předávejte hodnoty prostřednictvím parametrů:
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}");
}
Pro typy parametrů, velikosti, hodnoty NULL a směry viz Konfigurace parametrů. Nevkládejte nedůvěryhodné hodnoty do CommandText.
Provedení uložené procedury
Nastavte CommandType.StoredProcedure a použijte název procedury kvalifikovaný schématem:
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 podporuje CommandType.Text a CommandType.StoredProcedure. Nastavení CommandType.TableDirect vyvolá ArgumentOutOfRangeException.
Zkontrolujte, co každá metoda vrací
Použijte ExecuteScalar , když potřebujete jednu hodnotu:
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 vrací null, když výsledek nemá žádné řádky a DBNull.Value, když je první hodnota databázová NULL.
Použijte ExecuteNonQuery pro příkazy měnící data. Tento příklad vrací zpět svou změnu, takže AdventureWorks zůstává beze změny:
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 potlačuje počty ovlivněných řádků, takže ExecuteNonQuery může vrátit i -1 tehdy, když příkaz změní data.
Použijte ExecuteXmlReader pro FOR XML výsledek:
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());
Použijte lokální transakci
Když má spojení aktivní lokální SqlTransaction, je této transakci přiřazen každý příkaz provedený v tomto spojení. Tento příklad vrátí svou změnu zpět, takže AdventureWorks zůstává beze změny:
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();
Volejte Commit místo Rollback pouze tehdy, když aplikace přijme celou transakci. Příkaz, který neodkazuje na aktivní transakci, hodí InvalidOperationException. Provádění také selže, pokud transakce patří jinému připojení. Pro hranice transakcí a rollback viz Lokální transakce.
Nastavte časový limit příkazu
CommandTimeout omezuje provádění příkazů a kumulativní čekání na čtení ze sítě v sekundách. Příkaz používá nastavení připojení Command Timeout, pokud je nakonfigurováno. Jinak je výchozí doba 30 sekund. Hodnota 0 nemá žádné časové omezení. Záporné hodnoty vyvolají ArgumentException.
Když vyprší časový limit, příkaz hodí SqlException s Number nastaveným na -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 Omezuje navazování spojení a čekání ve frontě poolu.
CommandTimeout začíná po spuštění příkazu. Pro více informací viz Možnosti připojení.
Používejte konečný časový limit a token zrušení společně. Časový limit stanovuje limit pro databázovou operaci. Zrušení tokenu může vrátit kontrolu volajícímu před vypršením timeoutu. Nepředpokládejte, že zrušení a časový limit vyvolají stejnou výjimku.
Znovu použít a připravit příkazy
Přidejte parametr jednou a poté po dokončení každého spuštění změňte jeho hodnotu:
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)}");
}
}
Použijte Prepare jen tehdy, když to naměřené hodnoty ospravedlňují.
Prepare Nepřipravuje uložené procedury ani textové příkazy bez parametrů. Pro parametrizovaný text nastavte kompletní metadata, jako jsou Size, Precision a Scale, na každý parametr předtím, než zavoláte Prepare.
Příkazy k řešení problémů
Zachyťte SqlException při databázové operaci a zkontrolujte její Errors kolekci chyb, když server vrátí více než jednu chybu. Pro chyby příkazů, varování a informační zprávy viz Zvládání chyb a zpráv.
Používejte diagnostické čítače, trasování zdrojů událostí a průvodce SqlClient pro řešení problémů, když chyba vyžaduje více kontextu. Aplikujte konfigurovatelnou logiku opakovaného pokusu pouze tehdy, když je bezpečné opakovat příkaz.