Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Gunakan SqlCommand untuk menjalankan pernyataan Transact-SQL (T-SQL) atau prosedur tersimpan. Sebuah perintah membutuhkan SqlConnection yang terbuka. Buang command setelah digunakan, dan buang reader sebelum Anda menggunakan kembali koneksi.
Contoh dalam artikel ini mengasumsikan bahwa sebuah objek terbuka SqlConnection bernama connection menargetkan database contoh AdventureWorks.
Contoh C# membutuhkan using Microsoft.Data.SqlClient;. Contoh yang menggunakan SqlDbType, CommandBehavior, atau using System.Data; juga membutuhkan CommandType.
Untuk penyiapan koneksi, autentikasi, dan enkripsi, lihat String koneksi dan Enkripsi dan validasi sertifikat.
Pilih metode eksekusi
Pilih metode yang sesuai dengan hasil yang diharapkan:
| Metode | Gunakan ketika diperlukan | Hasil |
|---|---|---|
| ExecuteNonQuery | Perintah ini mengubah data atau skema. | Jumlah baris yang terpengaruh.
-1 dapat terjadi ketika tidak ada hitungan yang tersedia, termasuk saat SET NOCOUNT ON menyembunyikan jumlah. |
| ExecuteScalar | Anda memerlukan satu nilai. | Kolom pertama dari baris pertama, atau null ketika hasilnya tidak memiliki baris. Sebuah database NULL dikembalikan sebagai Value. |
| ExecuteReader | Anda membutuhkan baris, beberapa set hasil, atau skema. | SqlDataReader. |
| ExecuteXmlReader | Perintah mengembalikan XML dalam bentuk yang dibutuhkan oleh ExecuteXmlReader. |
Sebuah XmlReader. |
Setiap metode memiliki padanan asinkron berbasis tugas. Berikan CancellationToken saat pemanggil perlu berhenti menunggu. Untuk perilaku pembatalan dan timeout, lihat Pemrograman asinkron.
Eksekusi perintah teks
CommandType.Text adalah default. Tempatkan pernyataan di dalam CommandText dan lewatkan nilai melalui parameter:
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}");
}
Untuk tipe parameter, ukuran, nilai null, dan arah, lihat Konfigurasikan parameter. Jangan menggabungkan nilai yang tidak tepercaya ke dalam CommandText.
Menjalankan prosedur tersimpan
Atur CommandType.StoredProcedure dan gunakan nama prosedur yang dikualifikasi skema:
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 mendukung CommandType.Text dan CommandType.StoredProcedure. Pengaturan ArgumentOutOfRangeException memunculkan CommandType.TableDirect.
Periksa apa yang dikembalikan setiap metode
Gunakan ExecuteScalar saat Anda membutuhkan satu nilai:
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 Mengembalikan null ketika hasil tidak memiliki baris dan DBNull.Value ketika nilai pertama adalah nilai database NULL.
Gunakan ExecuteNonQuery untuk pernyataan yang mengubah data. Contoh ini membatalkan perubahannya sehingga AdventureWorks tetap tidak berubah:
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 menyembunyikan hitungan baris yang terpengaruh, sehingga ExecuteNonQuery dapat mengembalikan -1 bahkan ketika sebuah pernyataan mengubah data.
Gunakan ExecuteXmlReader untuk hasil FOR XML:
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());
Gunakan transaksi lokal
Ketika sebuah koneksi memiliki SqlTransaction lokal yang aktif, tetapkan transaksi tersebut ke setiap perintah yang dijalankan pada koneksi tersebut. Contoh ini membatalkan perubahannya sehingga AdventureWorks tetap tidak berubah:
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();
Panggil Commit saja, bukan Rollback, hanya ketika aplikasi menerima transaksi lengkap. Perintah yang tidak merujuk pada transaksi aktif akan menghasilkan InvalidOperationException. Eksekusi juga gagal jika transaksi milik koneksi lain. Untuk batas transaksi dan rollback, lihat Transaksi lokal.
Atur timeout perintah
CommandTimeout membatasi eksekusi perintah dan waktu tunggu pembacaan jaringan kumulatif dalam hitungan detik. Sebuah perintah menggunakan pengaturan koneksi Command Timeout saat pengaturan tersebut dikonfigurasi. Jika tidak, default-nya adalah 30 detik. Nilai dari 0 tidak memiliki batas waktu. Nilai negatif menimbulkan ArgumentException.
Ketika timeout habis, perintah akan melempar SqlException dengan Number set ke -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 membatasi pendirian koneksi dan waktu tunggu pool.
CommandTimeout dimulai setelah eksekusi perintah dimulai. Untuk informasi lebih lanjut, lihat Opsi Koneksi.
Gunakan timeout terbatas dan token pembatalan bersamaan. Timeout menetapkan batas operasi database. Membatalkan token dapat mengembalikan kontrol kepada pemanggil sebelum timeout berakhir. Jangan berasumsi bahwa pembatalan dan timeout menghasilkan pengecualian yang sama.
Gunakan kembali dan menyiapkan perintah
Tambahkan parameter sekali, lalu ubah nilainya setelah setiap eksekusi selesai:
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)}");
}
}
Hubungi Prepare hanya jika pengukuran membenarkannya.
Prepare tidak menyiapkan prosedur tersimpan atau perintah teks tanpa parameter. Untuk teks yang diparameterisasi, atur metadata lengkap seperti Size, Scale, dan Prepare pada setiap parameter sebelum Anda memanggil Precision.
Memecahkan masalah pada perintah
Tangkap SqlException di sekitar operasi basis data dan periksa koleksi Errors saat server mengembalikan lebih dari satu kesalahan. Untuk kesalahan perintah, peringatan, dan pesan informasi, lihat Menangani kesalahan dan pesan.
Gunakan counter diagnostik, pelacakan sumber event, dan panduan pemecahan masalah SqlClient ketika kesalahan membutuhkan konteks lebih lanjut. Terapkan logika retry yang dapat dikonfigurasi hanya ketika pengulangan perintah aman.