首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

C# SqlDataAdapter 完整使用指南:建構、Fill、Update 與效能陷阱

     編輯:關於SqlServer

SqlDataAdapter:DataSet 與 SQL Server 的橋樑

SqlDataAdapter 封裝 SelectCommand、InsertCommand、UpdateCommand、DeleteCommand,負責 Fill(資料源 → DataSet)與 Update(DataSet → 資料源)雙向同步。本文涵蓋三種建構方式、TableMapping、連線管理、重複 Fill 陷阱與最佳實務。

一、三種建構 SqlDataAdapter 的方式

// 1. 連接字串 + SQL 字串(簡單但每次新建連線)
var da1 = new SqlDataAdapter("SELECT * FROM Customers", connStr);

// 2. SQL 字串 + SqlConnection 物件(可重用連線)
using (var conn = new SqlConnection(connStr)) {
    var da2 = new SqlDataAdapter("SELECT * FROM Customers", conn);
}

// 3. SqlCommand 物件(最靈活,可預設參數、交易)
using (var conn = new SqlConnection(connStr)) {
    var cmd = new SqlCommand("SELECT * FROM Customers WHERE City = @City", conn);
    cmd.Parameters.AddWithValue("@City", "London");
    var da3 = new SqlDataAdapter(cmd);
}

建議:方式 2/3 可共用 SqlConnection,減少連線池壓力。

二、Fill 操作核心細節

  • 自動開關連線:若連線關閉,Fill 會自動開啟、查詢、關閉;若已開啟,則保持開啟狀態(開發者需自行關閉)。
  • TableMapping:預設產生 Table、Table1... 可用 da.TableMappings.Add("Table", "Customers") 或 da.Fill(ds, "Customers") 指定名稱。
  • 直接 Fill DataTable:da.Fill(dt) 比填 DataSet 再取 Table 更簡潔。

三、連線管理效能陷阱

// ❌ 錯誤:兩次 Fill 觸發兩次 Open/Close
daCustomers.Fill(ds, "Customers");
daOrders.Fill(ds, "Orders");

// ✅ 正確:手動控制連線週期
conn.Open();
daCustomers.Fill(ds, "Customers");
daOrders.Fill(ds, "Orders");
conn.Close();

批次填充多個 DataAdapter 時,**務必手動 Open/Close 共用連線**,避免頻繁連線池操作。

四、重複 Fill 的資料重複與過期問題

da.Fill(ds, "Customers");  // 第 1 次
// ... 業務邏輯 ...
da.Fill(ds, "Customers");  // 第 2 次:資料會**累加**(重複),且已刪除的列不會移除

解決方案:再次 Fill 前先清除舊資料:

ds.Tables["Customers"].Clear();  // 或 ds.Tables["Customers"].Rows.Clear()
da.Fill(ds, "Customers");

若表有主鍵,Fill 會依主鍵合併(Upsert),但仍無法偵測資料源端已刪除的列。

五、UpdateCommand 執行機制

  • 呼叫 da.Update(ds, "Table") 時,掃描 DataTable 所有列的 RowState。
  • 僅對 Added/Modified/Deleted 列執行對應 Command。
  • 未修改的列完全不執行 SQL,極省資源。

六、CommandBuilder 自動產生指令(僅限單表、有主鍵)

var da = new SqlDataAdapter("SELECT * FROM Customers", conn);
var cb = new SqlCommandBuilder(da);  // 自動產生 Insert/Update/DeleteCommand
da.UpdateCommand = cb.GetUpdateCommand();
// 現在可直接 da.Update(ds) 同步修改

限制:複雜 Join、無主鍵、預存程序場景需手寫 Command。

七、完整範本:查詢 → 修改 → 同步回資料庫

using (var conn = new SqlConnection(connStr))
using (var da = new SqlDataAdapter("SELECT * FROM Customers WHERE Country = 'UK'", conn))
using (var cb = new SqlCommandBuilder(da)) {
    var dt = new DataTable();
    da.Fill(dt);
    
    // 業務層修改 dt.Rows...
    dt.Rows[0]["ContactName"] = "New Name";
    dt.Rows.Add(dt.NewRow() { ["CustomerID"] = "NEW01", ["Country"] = "UK" });
    
    da.Update(dt);  // 批次同步
}

總結:SqlDataAdapter 黃金法則

  1. 優先使用 SqlCommand + SqlConnection 建構(方式 3)。
  2. 批次 Fill 多表時,手動 Open() 共用連線。
  3. 重複 Fill 同表前 **Clear()** 避免重複與過期資料。
  4. 單表有主鍵 → 善用 SqlCommandBuilder 減少樣板碼。
  5. 僅執行單一 SQL/預存程序 → 直接用 SqlCommand.ExecuteNonQuery/Reader/Scalar,別用 DataAdapter。

遵循這些原則,SqlDataAdapter 將成為穩定高效的離線資料同步利器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved