简体   繁体   English

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

[英]Entity Framework (Core) - cascading delete

I'm using EF Core 3.1.1, but I believe this question applies to all versions of EF.我使用的是 EF Core 3.1.1,但我相信这个问题适用于所有版本的 EF。

It seems the EF has the ability to cascade delete - if it is enabled, and if the dependent objects are loaded in the context. EF 似乎具有级联删除的能力 - 如果它已启用,并且依赖对象是否已在上下文中加载。

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

The above statement deletes all the blog's posts, and then the blog - each with a different sql statement.上面的语句删除了所有博客的帖子,然后是博客——每个都有不同的 sql 语句。

This is what I want, however when using code-first, it also creates the tables with cascading delete enabled in the database.这就是我想要的,但是在使用代码优先时,它还创建了在数据库中启用级联删除的表。 ( ON DELETE CASCADE ) ON DELETE CASCADE

Can you enable cascade delete in EF, and rely of EF deleting dependent objects, without also enabling database level cascade delete?是否可以在 EF 中启用级联删除,并依赖 EF 删除依赖对象,而不启用数据库级级联删除? (Or am I understanding this incorrectly?) (还是我理解错误?)

The reason is migrations fail because SQL won't enable cascade delete in the database because it detects multiple cascade paths (even though multiple wouldn't occur naturally in the schema)原因是迁移失败,因为 SQL 不会在数据库中启用级联删除,因为它检测到多个级联路径(即使多个不会在架构中自然发生)

Thanks!谢谢!

Actually EF Core 3.0 is the first version of EF which adds such capability via DeleteBehavior.ClientCascade option (unfortunately not yet included in the Cascade Delete section of the documentation):实际上,EF Core 3.0 是 EF 的第一个版本,它通过DeleteBehavior.ClientCascade选项添加了此类功能(遗憾的是尚未包含在文档的 级联删除部分):

For entities being tracked by the DbContext , dependent entities will deleted when the related principal is deleted.对于DbContext跟踪的实体,删除相关主体时将删除依赖实体。

If the database has been created from the model using Entity Framework Migrations or the EnsureCreated() method, then the behavior in the database is to generate an error if a foreign key constraint is violated.如果数据库是使用实体框架迁移或EnsureCreated()方法从模型创建的,则数据库中的行为是在违反外键约束时生成错误。

Shortly, all Client* delete behaviors are mapped to Restrict , ie enforced FK relationship in database without cascade.很快,所有Client*删除行为都映射到Restrict ,即在数据库中强制执行 FK 关系而无需级联。 Client behavior apply only on entities tracked by the context, so make sure you Include the related data before deleting (as in your sample).客户端行为仅适用于上下文跟踪的实体,因此请确保在删除之前Include相关数据(如您的示例中所示)。

To configure the option, you'd need fluent API at minimum having valid Has + With in order to get to OnDelete method, eg要配置该选项,您至少需要具有有效的Has + With流畅 API 才能使用OnDelete方法,例如

modelBuilder.Entity<Blog>()
    .HasMany(e => e.Posts)
    .WithOne(e => e.Blog)
    .OnDelete(DeleteBehavior.ClientCascade); 

You can add the Cascade Behavior to your entities as below.您可以将级联行为添加到您的实体,如下所示。 inside OnModelCreating;在 OnModelCreating 里面;

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

在此处输入图片说明

Thanks for the comments/posts.感谢您的评论/帖子。

My EF model classes and configuration are correct.我的 EF 模型类和配置是正确的。 The issue is my schema has places where multiple cascade paths exist, which ok because the primary item in those paths are never deleted (soft-deleted).问题是我的架构有多个级联路径存在的地方,这是可以的,因为这些路径中的主要项目永远不会被删除(软删除)。 While EF does not have an issue with multiple cascade paths, SQL sure does, and SQL throws errors when trying to update the database.虽然 EF 没有多个级联路径的问题,但 SQL 确实有问题,并且 SQL 在尝试更新数据库时会引发错误。

I didn't want disable cascade deletes and set up elaborate cascading functionality in code, just because of a couple places where multiple cascade paths exist.我不想禁用级联删除并在代码中设置复杂的级联功能,只是因为存在多个级联路径的几个地方。

However, the problem is I wasn't thinking about this correctly.但是,问题是我没有正确考虑这一点。 All I really have to do is disable cascading on the FKs that cause the multiple paths, and leave it enabled for the rest.我真正需要做的就是在导致多个路径的 FK 上禁用级联,并在其余部分启用它。 I think I was just burnt out when I asked this question.当我问这个问题时,我想我已经筋疲力尽了。 :) :)

For ef core 3 you do not need anythink in "WithOne"对于 ef core 3,您不需要在“WithOne”中进行任何思考

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM