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

LINQ to SQL 級聯操作完全指南:新增、更新、刪除與複雜場景實戰

     編輯:關於.NET

關係類型與級聯支援現狀

關係級聯新增級聯更新級聯刪除
一對多 (Order → Order_Details)✅ 內建支援✅ 智能追蹤❌ 需手動處理
一對一✅✅❌
多對多✅ (透過關聯實體)✅❌

範例環境:Northwind 資料庫 Order / Order_Details

ER 圖

1. 級聯新增:父子同步持久化

protected void btnCascadeAdd_Click(object sender, EventArgs e)
{
    using (var db = new DataClasses2DataContext())
    {
        Orders order = new Orders
        {
            ShipCountry = "China",
            CustomerID = "ALFKI",
            EmployeeID = 1,
            ShipVia = 1
        };

        for (int i = 1; i < 5; i++)
        {
            order.Order_Details.Add(new Order_Details
            {
                Discount = 0.2f,
                Quantity = (short)i,
                ProductID = i
            });
        }

        db.Orders.InsertOnSubmit(order);
        db.SubmitChanges(); // 單一 Transaction 完成父子寫入
    }
}

SQL Profiler 驗證:先 INSERT Order 取得 Identity,再批次 INSERT Order_Details,隱式交易保證原子性。

2. 級聯更新:智能變更追蹤

protected void btnCascadeUpdate_Click(object sender, EventArgs e)
{
    using (var db = new DataClasses2DataContext())
    {
        Orders order = db.Orders.Single(o => o.OrderID == 11120);
        order.ShipAddress = "江蘇省昆山市安博路1號";

        foreach (var detail in order.Order_Details)
        {
            detail.Discount = 0.1f; // 批量修改子物件
        }

        db.SubmitChanges(); // 僅發出必要 UPDATE 陳述式
    }
}

LINQ to SQL 比較原始值與目前值,只更新實際變更的欄位,產生精簡 SQL。

3. 級聯刪除:官方不支援,兩種替代方案

方案 A:手動刪除子集合 (推薦,邏輯明確)

protected void btnCascadeDelete_Click(object sender, EventArgs e)
{
    using (var db = new DataClasses2DataContext())
    {
        Orders order = db.Orders.Single(o => o.OrderID == 11127);
        db.Order_Details.DeleteAllOnSubmit(order.Order_Details); // 先刪子
        db.Orders.DeleteOnSubmit(order); // 再刪父
        db.SubmitChanges();
    }
}

方案 B:DBML 設定 DeleteOnNull="true" + 資料庫 CASCADE

  1. 開啟 .dbml 為 XML,修改關聯:<Association ... DeleteOnNull="true" />
  2. 資料庫外鍵加上 ON DELETE CASCADE
  3. 直接 db.Orders.DeleteOnSubmit(order); db.SubmitChanges();

原理:DeleteOnNull 允許子物件在記憶體中成為孤兒,提交時資料庫級聯刪除。

4. 複雜混合操作:同一交易中增刪改並存

protected void btnComplexOp_Click(object sender, EventArgs e)
{
    using (var db = new DataClasses2DataContext())
    {
        Orders order = db.Orders.Single(o => o.OrderID == 11126);

        // 父屬性修改
        order.ShipAddress = "昆山軟體外包實訓基地";
        order.ShipCity = "China";

        // 移除第 3 筆明細
        order.Order_Details.RemoveAt(2);

        // 修改最後一筆明細
        order.Order_Details.Last().Discount = 0.7f;

        // 新增兩筆明細
        for (int i = 10; i < 12; i++)
        {
            order.Order_Details.Add(new Order_Details
            {
                Discount = 0.4f,
                Quantity = (short)i,
                ProductID = i
            });
        }

        db.SubmitChanges(); // 全部在單一交易完成
    }
}

執行前資料

執行後資料

關鍵注意事項

  • 關聯屬性必須為 EntitySet<T>:設計工具產生的 Order_Details 才支援級聯
  • 手工類別需實作 INotifyPropertyChanged/INotifyPropertyChanging:否則變更追蹤失效
  • 交易範圍:SubmitChanges() 預設隱式交易,可用 TransactionScope 跨 DataContext
  • 並發衝突:Column(IsVersion=true) 或 UpdateCheck 處理樂觀鎖
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved