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

Castle ActiveRecord 實戰(5):多對多關聯映射完整實作——HasAndBelongsToMany 詳解與級聯操作

     編輯:關於.NET

資料庫結構:中介表模式

多對多關聯需一張中介表存放雙向外鍵:

CREATE TABLE Blogs (
    blog_id int IDENTITY PRIMARY KEY,
    blog_name varchar(50),
    blog_author varchar(50)
);

CREATE TABLE Communities (
    community_id int IDENTITY PRIMARY KEY,
    community_name varchar(50),
    community_intro varchar(500)
);

CREATE TABLE Blog_Community (
    blog_id int NOT NULL,
    community_id int NOT NULL,
    PRIMARY KEY (blog_id, community_id)
);

實體映射:雙向 HasAndBelongsToMany

在兩端實體各自宣告集合屬性,指向同一中介表:

[ActiveRecord("Blogs")]
public class Blog : ActiveRecordBase {
    // ... Id, Name, Author

    [HasAndBelongsToMany(typeof(Community), 
        Table = "Blog_Community",
        ColumnKey = "blog_id",       // 本端外鍵欄位
        ColumnRef = "community_id")] // 對端外鍵欄位
    public IList Communities { get; set; }
}

[ActiveRecord("Communities")]
public class Community : ActiveRecordBase {
    // ... Id, Name, Intro

    [HasAndBelongsToMany(typeof(Blog),
        Table = "Blog_Community",
        ColumnKey = "community_id",
        ColumnRef = "blog_id")]
    public IList Blogs { get; set; }
}

三個必要參數:Table(中介表名)、ColumnKey(本端 FK)、ColumnRef(對端 FK)不可省略。

HasAndBelongsToMany 完整屬性表

屬性說明範例值
Cascade級聯操作模式None / SaveUpdate / Delete / All / AllDeleteOrphan
Inverse哪一端負責維護關聯(建議一端 true)true / false
Schema資料庫 Schema 名稱"dbo"
Where額外 SQL Where 條件"IsActive = 1"
Lazy延遲載入true / false

級聯操作模式詳解

模式行為
None不級聯,需手動儲存關聯物件
SaveUpdate儲存/更新主體時,自動 Save/Update 關聯物件
Delete刪除主體時,自動 Delete 關聯物件(慎用!會刪除對端實體)
AllSaveUpdate + Delete
AllDeleteOrphanAll + 移除集合中項目時自動刪除該關聯記錄(中介表資料)

多對多典型設定:Cascade = ManyRelationCascadeEnum.SaveUpdate(只維護中介表關聯,不刪除 Community 實體)。

完整測試案例:級聯新增、更新、刪除

1. 級聯新增:建立 Blog 並關聯多個 Community

[Test]
public void TestCascadingSave() {
    var blog = new Blog { Name = "Tech Space", Author = "Terrylee" };
    blog.Communities = new ArrayList { Community.Find(1), Community.Find(2) };
    blog.Save(); // 自動寫入 Blog_Community
}

2. 級聯更新:新增/移除關聯

[Test]
public void TestCascadingUpdate() {
    // 從 Blog 端新增關聯
    var blog = Blog.Find(10);
    blog.Communities.Add(Community.Find(3));
    blog.Communities.Add(Community.Find(4));
    blog.Save();

    // 從 Community 端新增關聯(雙向維護)
    var community = Community.Find(3);
    community.Blogs.Add(Blog.Find(8));
    community.Save();
}

3. 級聯刪除:只刪中介表資料,保留實體

[Test]
public void TestCascadingDelete() {
    using (var tran = new TransactionScope()) {
        try {
            var blog = Blog.Find(10);
            blog.Delete(); // 刪除 Blog 及 Blog_Community 關聯記錄
            tran.VoteCommit();
        } catch { tran.VoteRollBack(); }
    }

    // 刪除 Community 同理,不會連帶刪除 Blog 實體
}

Inverse 端設定避免重複更新中介表

雙向關聯建議一端設 Inverse = true,表示由另一端負責維護中介表:

[HasAndBelongsToMany(..., Inverse = true)]
public IList Communities { get; set; }

否則雙端 Save 都會嘗試 Insert/Update 中介表,導致重複鍵錯誤或效能浪費。

總結

多對多映射核心在於正確設定中介表三要素(Table, ColumnKey, ColumnRef)與級聯策略。配合 Inverse 避免雙向維護衝突,SaveUpdate 級聯模式滿足多數業務需求。掌握這些設定,即可優雅處理複雜的多對多業務場景。

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