我在两张桌子之间有多对多的关系,让我们说朋友和食物。如果朋友喜欢食物,我会在FriendsFoods表中插入一行,如下所示:
ID Friend Food
1 'Tom' 'Pizza'
FriendsFoods分别有一个主键'ID'和两个非空外键'Friend'和'Food'到'Friends'和'Foods'表。
现在假设我有一个与{Tom'对应的Friend tom
.NET对象,Tom不再喜欢披萨了(他怎么了?)
FriendsFoods ff = tom.FriendsFoods.Where(x => x.Food.Name == 'Pizza').Single();
tom.FriendsFoods.Remove(ff);
pizza.FriendsFoods.Remove(ff);
如果我尝试在DataContext上SubmitChanges()
,我会收到异常,因为它会尝试在Friend
表的Food
和FriendsFoods
列中插入空值。
我确信我可以整理某种复杂的逻辑来跟踪对FriendsFoods
表的更改,拦截SubmitChanges()
调用等,以尝试按照我想要的方式工作,但是是否有一种很好的,干净的方法来删除与LINQ-To-SQL的多对多关系?
答案 0 :(得分:3)
假设数据库本身在外键上定义了CASCADE DELETE
个规则(否则你遇到麻烦),你需要在Linq to SQL中的每个关系上设置删除规则设计师(或DeleteRule
中的AssociationAttribute
)至CASCADE
。
您也无需删除关联的两面 - 只需从tom
或pizza
删除。
附录 @Crispy也是正确的,因为您关注的真实属性是子关联中的DeleteOnNull
属性。 但是,您在设计器中看不到这一点的原因是设计人员根据(a)父级到CASCADE
设置自动检测此属性的值--child关联,以及(b)外键字段是否可为空。如果在Linq to SQL设计器中有一个不可为空的FK且CASCADE DELETE
,它应自动为子到父关联设置DeleteOnNull = true
,然后从映射表中删除记录而不是试图将其关联设置为NULL
。
答案 1 :(得分:3)
如果您尝试通过从linq实体的子集合中删除多对多表(FriendFoods
)中的条目,则需要设置{{1}在dbml文件中,关系的属性等于true。不幸的是,你不能通过dbml设计器来做到这一点。您必须将.dbml文件作为xml文件打开,然后手动编辑该关联的xml。
请参阅How do I delete records from a child collection in LINQ to SQL?
答案 2 :(得分:2)
CASCADE DELETE不适用于此处。它仅适用于删除实体的情况,即Friend对象或Food对象,但如果您只是想删除该关系则不适用。 您是否有任何理由不直接访问关系表?我认为这将是一个更清洁的解决方案。