| 類別 | 核心職責 | 比喻 |
|---|---|---|
| DataSet | 記憶體中**離線資料容器**,可包含多個 DataTable、關聯、約束。不直接連線資料庫。 | 「離線資料倉庫」 |
| DataAdapter | **橋樑/搬運工**,持有 Select/Insert/Update/Delete 四個 Command,負責 Fill() 將資料從資料庫載入 DataSet,Update() 將 DataSet 變更回寫資料庫。 | 「資料搬運車」 |
// 1. 建立連線與命令
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand("SELECT * FROM Users", conn))
{
// 2. 建立 DataAdapter (自動產生 Insert/Update/Delete Command,需設定 SelectCommand)
var adapter = new SqlDataAdapter(cmd);
// 或手動指定四個 Command 以獲得完全控制
// 3. 建立 DataSet
var ds = new DataSet();
// 4. Fill: 開啟連線 → 執行 SelectCommand → 讀取結果 → 填充 DataTable → 關閉連線
adapter.Fill(ds, "Users"); // 第二參數指定 DataTable 名稱
// 5. 離線操作 DataSet (新增/修改/刪除 DataRow)
var table = ds.Tables["Users"];
var newRow = table.NewRow();
newRow["Name"] = "Alice";
newRow["Email"] = "alice@example.com";
table.Rows.Add(newRow);
// 6. Update: 依 RowState (Added/Modified/Deleted) 批次執行對應 Command
adapter.Update(ds, "Users"); // 自動開啟/關閉連線,交易內執行
}
SelectCommand:必須設定,Fill() 依賴它。InsertCommand/UpdateCommand/DeleteCommand:Update() 時使用。可用 SqlCommandBuilder 自動產生 (需主鍵、單表)。MissingSchemaAction:AddWithKey 讓 Fill() 同時載入主鍵資訊,否則 Update() 可能失效。TableMappings:對應資料表與 DataTable 名稱 (預設 "Table", "Table1"...)。Fill()/Update() 內部自動開啟/關閉連線,屬於**斷點連線**模式。adapter.Update() 才會回寫。Update() 預設用所有欄位舊值做 WHERE 條件,若資料被他人修改會拋 DBConcurrencyException,需處理衝突策略。var adapter = new SqlDataAdapter("SELECT * FROM Users", conn);
var builder = new SqlCommandBuilder(adapter); // 自動根據 SelectCommand 反推 Insert/Update/Delete
builder.QuotePrefix = "["; builder.QuoteSuffix = "]"; // SQL Server 識別字元
// 現在可以直接 adapter.Update(ds)
DataAdapter 是 DataSet 與資料庫之間的「翻譯官與搬運工」。DataSet 負責「存」,DataAdapter 負責「取」與「寫」。掌握四大 Command、RowState、CommandBuilder、並發處理,即可熟練運用 ADO.NET 離線架構開發高效能資料存取層。