使用 EF Core 进行级联删除

Posted

技术标签:

【中文标题】使用 EF Core 进行级联删除【英文标题】:Cascade deleting with EF Core 【发布时间】:2018-07-19 09:59:02 【问题描述】:

目前我在使用 EF Core 时遇到了一些问题。我有一些需要删除的数据,我正在努力了解流畅的 API 是如何工作的,确切地说是 .OnDelete() 函数。

考虑到来自 microsofts own websites 的经典博客/帖子场景,我想知道 OnDelete() 到底是什么实体是“目标”(因为没有更好的词)在某些情况下它似乎是博客,在其他情况下,帖子。是否可以从双方定义级联删除(当父博客存在时删除帖子)如果是这样我想代码应该如下所示:

model.Entity<Post>().HasOne(p => p.Blog).WithMany(b => b.Posts).HasForeignKey(p => p.BlogId).OnDelete(DeleteBehavior.Cascade)

据我了解,这是说“删除博客时,首先删除所有引用此博客的帖子”,这意味着 OnDelete(DeleteBehavior.Cascade)适用于博客,而不是发布。

但那是一样的吗?

model.Entity<Blog>().HasMany(b => b.Posts).WithOne(p => p.Blog).OnDelete(DeleteBehavior.Cascade)

或者OnDelete(DeleteBehavior.Cascade) 是否适用于帖子而不是博客?

【问题讨论】:

【参考方案1】:

级联删除总是在一个方向上起作用 - 从 主要实体从属实体,即删除主要实体会删除从属实体。对于一对多关系,one 方始终是 principalmany 方始终是 从属 .

您似乎对流畅的配置感到困惑。请注意,每个关系都由两端组成。流畅的配置允许您从一端开始并将其与另一端相关联,反之亦然,但您仍然在配置(定义)single 关系。所以

Entity<A>().HasOne(a => a.B).WithMany(b => b.As)

相同
Entity<B>().HasMany(b => b.As).WithOne(a => a.B);

它们都定义了一个相同的关系。选择哪一个并不重要,只需为每个关系使用单个配置以避免差异。

话虽如此,

model.Entity<Post>().HasOne(p => p.Blog).WithMany(b => b.Posts)
    .HasForeignKey(p => p.BlogId)
    .OnDelete(DeleteBehavior.Cascade);

model.Entity<Blog>().HasMany(b => b.Posts).WithOne(p => p.Blog)
    .HasForeignKey(p => p.BlogId)
    .OnDelete(DeleteBehavior.Cascade);

是一且相同的,定义了从BlogPost的单个一对多关系。由于Blogone 方,Postmany 方,Blog主要实体,@987654333 @ 是依赖实体,因此删除Blog 将删除相关的Posts。

参考:

Relationships - Definition of terms Cascade Delete

【讨论】:

非常感谢您提供非常明确的答案 :) 我刚刚读到 SQL Server 仅支持从表上的一个 FK 中级联删除。这意味着我不能真正依赖级联删除,仍然必须在我的删除函数中实现某些相关对象的删除,对吧? 我猜你的意思是所谓的多级联路径。是的,SqlServer 有这样的问题,并且该规则适用于 EF (Core) 模型。只要它们不形成循环,就有可能与级联删除有多个 FK 关系。您应该始终尝试强制级联删除,如果更新数据库因多个级联路径异常而失败,那么您应该打破循环,但为一个或多个关系关闭级联删除,并手动为它们处理相关数据的删除。 在级联删除“循环”时是否有一些资源可以很好地描述? 我不记得了。但我会给你一个例子。假设你有关系 A -> B -> D 和 A -> C -> D。当你删除 A 时,它会删除相关的 B 和 C。相关的 Ds 可以通过 A -> Bs 或 A -> Cs 删除,因此你有循环(或多个级联路径)。 @variable 给你Configuring cascading behaviors

以上是关于使用 EF Core 进行级联删除的主要内容,如果未能解决你的问题,请参考以下文章

如何在 EF 代码优先中禁用链接表的级联删除?

15.翻译系列:EF 6中的级联删除EF 6 Code-First 系列

EF 级联删除

使用共享主键关联时,EF 4.1 Code First 中的级联删除规则

EF Code首先级联删除外键一对多

.Net开源数据库设计工具Mr.E For Linq (EF 6.1) 教程级联删除和触发器