使用 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 方始终是 principal,many 方始终是 从属 .
您似乎对流畅的配置感到困惑。请注意,每个关系都由两端组成。流畅的配置允许您从一端开始并将其与另一端相关联,反之亦然,但您仍然在配置(定义)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);
是一且相同的,定义了从Blog
到Post
的单个一对多关系。由于Blog
是 one 方,Post
是 many 方,Blog
是 主要实体,@987654333 @ 是依赖实体,因此删除Blog
将删除相关的Post
s。
参考:
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 进行级联删除的主要内容,如果未能解决你的问题,请参考以下文章
15.翻译系列:EF 6中的级联删除EF 6 Code-First 系列