在 ADO.NET 1.x 時代,SqlDataAdapter.Update 會針對 DataSet 中每一筆異動逐一發送 SQL 指令,造成大量往返。ADO.NET 2.0 引入 UpdateBatchSize 屬性,允許將多條 INSERT/UPDATE/DELETE 打包在單一網路封包中送出,大幅降低 Round-trip 成本。
| 屬性 | 預設值 | 說明 |
|---|---|---|
UpdateBatchSize | 1 | 每批次處理的資料列數;設為 >1 啟用批次更新,設為 0 由提供者自動決定最佳批次大小。 |
public partial class BatchUpdateForm : Form {
private SqlConnection conn;
private SqlDataAdapter dAdapt;
private DataSet dSet = new DataSet();
private StringBuilder logString = new StringBuilder();
public BatchUpdateForm() {
InitializeComponent();
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["AWConnectionString"].ConnectionString);
dAdapt = new SqlDataAdapter("SELECT ProductID, Name, ListPrice FROM Production.Product", conn);
// 註冊事件以觀察批次行為
dAdapt.RowUpdating += OnRowUpdating;
dAdapt.RowUpdated += OnRowUpdated;
}
private void getDataButton_Click(object sender, EventArgs e) {
dAdapt.Fill(dSet, "Product");
productGrid.DataSource = dSet.Tables["Product"];
}
private void updateDataButton_Click(object sender, EventArgs e) {
SqlCommandBuilder cb = new SqlCommandBuilder(dAdapt);
logString.Clear();
// 關鍵:設定批次大小(此處從 TextBox 取得)
dAdapt.UpdateBatchSize = int.Parse(batchSizeTextBox.Text);
dAdapt.Update(dSet.Tables["Product"]);
MessageBox.Show(logString.ToString());
}
void OnRowUpdating(object sender, SqlRowUpdatingEventArgs e) {
logString.AppendLine("Starting row update");
}
void OnRowUpdated(object sender, SqlRowUpdatedEventArgs e) {
logString.AppendLine("Completed row update");
}
}
RowUpdated 事件的 e.Status 需檢查 UpdateStatus.ErrorsOccurred,並透過 e.Row.RowError 逐筆處理。OracleDataAdapter.UpdateBatchSize)。UpdateBatchSize = 1 驗證邏輯正確,再調大批次。SqlCommandBuilder 自動產生指令,或手工指定 InsertCommand/UpdateCommand/DeleteCommand 以獲得最佳效能。SqlBulkCopy,效能優於批次更新。