实体框架(核心)-级联删除

16

我正在使用EF Core 3.1.1,但我认为这个问题适用于所有版本的EF。

看起来EF具有级联删除的功能-如果启用了它,并且依赖对象已加载到上下文中。

var blog = context.blogs.Include(x => x.Posts).First(x => x.BlogId == id);
context.blogs.Remove(blog);

上述语句会删除所有博客文章,然后是每个不同 SQL 语句的博客。

这正是我想要的,但使用 Code-First 时,它还会在数据库中启用级联删除并创建表。 (ON DELETE CASCADE)

你能否在 EF 中启用级联删除,并依靠 EF 删除相关对象,而不必同时启用数据库级别的级联删除?(或者我的理解有误吗?)

原因是迁移失败,因为 SQL 不会在数据库中启用级联删除,因为它检测到多个级联路径(即使在模式中自然情况下不会出现多个级联路径)。

谢谢!


1
你的想法是正确的,它确实是数据库服务器而不是Entity Framework Core执行级联删除。因此,EF无法处理此操作。如果迁移失败,因为数据库服务器警告存在多个级联路径,则是因为你没有正确配置流畅的API。也许如果你分享它,我们可以看一下是否有帮助? - Dennis VW
2
@Dennis1679 - 我在多个地方读到过这样的说法,如果依赖对象在db上下文中被加载,EF将通过执行SQL语句来删除它们,然后再删除对象。如果未加载依赖对象,则依靠数据库级联。这不是真的吗?也许只有在EF Core中才是真的?此外,模型已正确设置(我将在下面发布)-这是一个更一般的问题。 - J. Lee
4个回答

16
实际上,EF Core 3.0 是 EF 中第一个通过 DeleteBehavior.ClientCascade 选项添加此功能的版本(遗憾的是,该选项尚未包含在文档的Cascade Delete部分中):
对于由 DbContext 跟踪的实体,当相关的主实体被删除时,从属实体也会被删除。
如果使用 Entity Framework 迁移或 EnsureCreated() 方法从模型创建了数据库,则在数据库中的行为是:如果违反外键约束,则生成错误。
简而言之,所有 Client* 删除行为都映射到 Restrict,即在没有级联的情况下在数据库中强制执行 FK 关系。客户端行为仅适用于由上下文 跟踪 的实体,因此在删除之前,请确保 Include 相关数据(如示例中所示)。
要配置此选项,您至少需要使用有效的 Has + With 来获取 OnDelete 方法的流畅 API。
modelBuilder.Entity<Blog>()
    .HasMany(e => e.Posts)
    .WithOne(e => e.Blog)
    .OnDelete(DeleteBehavior.ClientCascade); 

2
谢谢Ivan - 这正是我在寻找的! - J. Lee
2
@yogihosting 它可以工作。仔细阅读答案和文档链接。在您的情况下,级联删除是从国家到城市,而不是您所认为的反过来。 - Ivan Stoev
1
谢谢@IvanStoev,我理解了并且能够整理我的代码。我检查了一下,在3.1 EF版本中不需要Include也不需要ClientCascade。在我的情况下,DeleteBehavior.Cascade是有效的,而且我也没有使用include来包含相关实体。 - yogihosting

4

您可以按照以下方式将级联行为添加到实体中:

在 OnModelCreating 内部实现如下:

foreach (var foreignKey in builder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
            {
                foreignKey.DeleteBehavior = DeleteBehavior.Cascade;
            }

enter image description here


2

对于 EF Core 3,您在 "WithOne" 中不需要任何内容。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
    .HasMany(e => e.Posts)
    .WithOne()
    .OnDelete(DeleteBehavior.ClientCascade); 
}

1

感谢您的评论/帖子。

我的EF模型类和配置是正确的。问题在于我的架构中存在多个级联路径,这是可以的,因为这些路径中的主要项目永远不会被删除(软删除)。虽然EF对于多个级联路径没有问题,但是SQL有问题,当尝试更新数据库时会抛出错误。

我不想在代码中禁用级联删除并设置复杂的级联功能,仅仅因为存在几个多重级联路径的地方。

然而,问题在于我没有正确思考这个问题。我只需要禁用导致多条路径的FK上的级联,然后将其保留在其他地方启用即可。我想当我提出这个问题时已经筋疲力尽了。 :)


1
抱歉我的回答不太对,我已经删除了。谢谢你提醒我。 - Akbar Asghari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接