多对多关系的实现(借助中间关系表)

多对多关系的实现(借助中间关系表)


核心思路

LINQ to SQL 本身只支持一对一和一对多关系,不直接支持多对多。要实现多对多,需要引入第三张关系表,将多对多拆解为两个一对多:


表结构设计

标签表(tag)

CREATE TABLE tag (
    id INT IDENTITY(1,1) PRIMARY KEY,
    name NVARCHAR(50) NULL
);Code language: PHP (php)

关系表(relatebooktag)— 拆桥表

CREATE TABLE relatebooktag (
    id INT IDENTITY(1,1) PRIMARY KEY,
    bid INT NULL,
    tid INT NULL,
    CONSTRAINT FK_relatebooktag_book FOREIGN KEY (bid) REFERENCES book(id),
    CONSTRAINT FK_relatebooktag_tag FOREIGN KEY (tid) REFERENCES tag(id)
);Code language: PHP (php)

关系模型:

┌─────────┐         ┌──────────────────┐         ┌─────────┐
│  book   │←── 1:N ─┤ relatebooktag    ├─ N:1 →  │  tag    │
│         │         │  (bid, tid)      │         │         │
└─────────┘         └──────────────────┘         └─────────┘Code language: CSS (css)

给书打标签(写入关系数据)

using (var db = new DataClasses1DataContext())
{
    // 要打标记的书
    var book = db.book.First(m => m.id == 12);

    // 准备要打的标签(可能不止一个)
    var tags = db.tag.ToList();

    // 逐条建立关系
    foreach (var item in tags)
    {
        var tb = new relatebooktag();
        tb.book = book;     // 设置导航属性,自动赋值 bid
        tb.tag = item;      // 设置导航属性,自动赋值 tid

        db.relatebooktag.InsertOnSubmit(tb);
    }

    // 一次提交,事务保证
    db.SubmitChanges();
}Code language: JavaScript (javascript)

不需要手动赋值外键:​ 通过 tb.book = booktb.tag = item,LINQ 自动将 book.iditem.id 填入 bidtid 字段。


查询某本书的所有标签

using (var db = new DataClasses1DataContext())
{
    var book = db.book.First(m => m.id == 12);

    // 通过关系表的集合导航,逐条取标签名
    foreach (var item in book.relatebooktag)
    {
        Console.WriteLine(book.name + " : " + item.tag.name);
    }
}Code language: JavaScript (javascript)

执行逻辑:

book → relatebooktag(一对多,延迟加载)→ tag(一对一,立即加载)

查询某个标签被哪些书使用

using (var db = new DataClasses1DataContext())
{
    var tag = db.tag.First(m => m.id == 1);

    // 通过关系表的集合导航,逐条取书名
    foreach (var item in tag.relatebooktag)
    {
        Console.WriteLine(tag.name + " : " + item.book.name);
    }
}Code language: JavaScript (javascript)

执行逻辑:

tag → relatebooktag(一对多,延迟加载)→ book(一对一,立即加载)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注