首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

ADO.NET 多資料表操作實戰:DataSet 填充、關聯更新與交易控制

     編輯:關於.NET

前言

DataSet 是 ADO.NET 離線架構的核心,宛如記憶體中的微型資料庫,支援多資料表、關聯、條件約束與異動追蹤。本文以 Northwind 資料庫為例,實作「多表填充」、「主從關聯顯示」、「關聯表更新」與「多 Command 交易」四大實戰場景,並揭露 SqlHelper.FillDataset 多表 Bug 修正方案。

一、資料庫與型別化 DataSet 準備

1.1 使用資料表

  • Customers(客戶)
  • Orders(訂單)
  • Order Details(訂單明細)

1.2 型別化 DataSet 設計

  • 名稱:DatasetOrders
  • 關聯:Customers → Orders → Order Details
  • Orders.OrderID 為 Identity,設定 `AutoIncrementSeed = -1`、`AutoIncrementStep = -1` 避免衝突

型別化 DataSet 設計圖

二、單一 DataAdapter 多結果集填充

2.1 儲存程序:GetCustomerOrdersInfo

CREATE PROCEDURE GetCustomerOrdersInfo
AS
SELECT CustomerID, CompanyName, ContactName FROM Customers WHERE CustomerID LIKE 'A%'
SELECT OrderID, OrderDate, CustomerID FROM Orders WHERE CustomerID IN (SELECT CustomerID FROM Customers WHERE CustomerID LIKE 'A%')
SELECT OrderID, ProductID, UnitPrice, Quantity, Discount FROM [Order Details] WHERE OrderID IN (SELECT OrderID FROM Orders WHERE CustomerID IN (SELECT CustomerID FROM Customers WHERE CustomerID LIKE 'A%'))

2.2 TableMappings 手動對應

public void FillCustomerOrdersInfo(DatasetOrders ds)
{
    using (var comm = new SqlCommand("GetCustomerOrdersInfo", _conn))
    using (var da = new SqlDataAdapter(comm))
    {
        comm.CommandType = CommandType.StoredProcedure;
        da.TableMappings.Add("Table", "Customers");
        da.TableMappings.Add("Table1", "Orders");
        da.TableMappings.Add("Table2", "Order Details");
        da.Fill(ds);
    }
}
  • 預設結果集命名 Table、Table1、Table2...
  • 必須明確映射至型別化 DataSet 的 DataTable 名稱

2.3 SqlHelper.FillDataset Bug 與修正

原始碼邏輯錯誤:

for (int i = 0; i < tableNames.Length; i++)
    tableName += (i + 1).ToString(); // 錯誤:Table、Table11、Table111...

修正版:

for (int i = 0; i < tableNames.Length; i++)
    da.TableMappings.Add(i == 0 ? "Table" : "Table" + i, tableNames[i]);

或直接呼叫修正後的 `FillDataset` 多載。

三、Windows Form 主從關聯顯示

3.1 三層 DataGrid 動態繫結

// 建構子
_ds.EnforceConstraints = false; // 關閉約束提升填充效能
dataGridCustomers.SetDataBinding(_ds, _ds.Customers.TableName);
dataGridOrders.SetDataBinding(_ds,
    _ds.Customers.TableName + "." + _ds.Customers.ChildRelations[0].RelationName);
dataGridOrderDetails.SetDataBinding(_ds,
    _ds.Customers.TableName + "." + _ds.Customers.ChildRelations[0].RelationName + "." +
    _ds.Orders.ChildRelations[0].RelationName);
  • `SetDataBinding(DataSource, DataMember)` 比單獨設定屬性更穩定
  • `DataMember` 使用關聯路徑:`ParentTable.ChildRelationName`

WinForm 執行畫面

四、關聯表更新策略

4.1 更新順序原則

  1. 父表先更新(Customers → Orders → Order Details)
  2. 刪除時反向:子表先刪

4.2 範例:批次更新

public void UpdateAll(DatasetOrders ds)
{
    // 假設已設定 DataAdapter 的 Insert/Update/DeleteCommand
    // 父表
    daCustomers.Update(ds.Customers);
    // 子表
    daOrders.Update(ds.Orders);
    daOrderDetails.Update(ds["Order Details"]);
}

五、多 Command 交易控制

public void BatchUpdateWithTransaction(DatasetOrders ds)
{
    _conn.Open();
    var tran = _conn.BeginTransaction();
    try
    {
        daCustomers.Update(ds.Customers);
        daOrders.Update(ds.Orders);
        daOrderDetails.Update(ds["Order Details"]);
        tran.Commit();
    }
    catch
    {
        tran.Rollback();
        throw;
    }
    finally { _conn.Close(); }
}
  • 所有 Command 指派同一 `SqlTransaction` 物件
  • 或使用 `TransactionScope` (System.Transactions) 簡化

六、DataReader 多結果集讀取替代方案

using (var comm = new SqlCommand("GetCustomerOrdersInfo", _conn))
{
    comm.CommandType = CommandType.StoredProcedure;
    _conn.Open();
    using (var reader = comm.ExecuteReader())
    {
        do
        {
            while (reader.Read())
                Console.WriteLine(reader[0]);
        } while (reader.NextResult());
    }
}
  • `NextResult()` 移至下一結果集
  • 唯讀、順向、低記憶體,適合大量資料串流處理

七、效能與最佳實務提醒

場景建議
大量資料填充`EnforceConstraints = false` 填充完再 `true`
頻繁更新使用 `BatchUpdate` 或 `SqlBulkCopy`
長時間交易縮短交易範圍,避免鎖定升級
型別化 vs 非型別化型別化提供 IntelliSense、編譯期檢查,維護性優

結語

DataSet 雖非最新技術,但在離線操作、多表關聯、XML 序列化、Web Service 傳輸等企業級場景仍具不可替代性。掌握 TableMappings、關聯路徑繫結、更新順序與交易控制,即能駕馭複雜多表業務邏輯。

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