EF核心:当DB-first FK出现错误时,如何级联删除?

时间:2019-02-08 14:08:28

标签: c# entity-framework-core cascade

考虑旧数据库的这个(令人困惑的)实体模型:

enter image description here

如您所见,模型Blog的集合中有Entry个集合,每个集合指向一个博客Post。箭头的尖端指向关系的主体/父母。至少这是EF核心基于外键存储位置看到它的方式。

不幸的是,EntryPost之间的FK是错误的处理方法,因为Post实际上是Entry的子元素;也就是说,当我从Entry删除Blog时,关联的Post也应删除。

由于我无法更改旧数据库的架构,所以我想知道如何建议EF级联删除Post,尽管它不认为它们是{{1 }}。

我尝试明确指定Entry无济于事:

DeleteBehavior

我还尝试将导航属性modelBuilder.Entity<Entry>() .HasOne(e => e.Post) .WithOne(p => p.Entry) .OnDelete(DeleteBehavior.Cascade); 设置为指示Post.Entry不能没有其Post才能生存,但这也没有帮助:

Entry

我目前正在检查owned entity types是否可以提供帮助,但我对此表示怀疑。

我想我需要的是一种明确声明实体关系的父/本的方法。像SetPrincipalEntityType()之类的东西。

当然,我总是可以手动删除public class Post { // ... [Required] [InverseProperty(nameof(Entry.Post))] public Entry Entry { get; set; } } ,但是我正试图避免这种情况。

有任何想法吗?

工作示例

我用集成测试创建了一个test project,可用于重现该问题:

Post

测试DeletesTextWhenDeletingReview将失败。

1 个答案:

答案 0 :(得分:0)

我在EF Core GitHub页面上发布了相同的问题。 solution posted there的想法是在SaveChanges()的替代中找到孤立的实体,然后手动将其删除:

public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
    // Note that this is internal code to force cascade deletes to happen.
    // It may stop working in any future release.
    ChangeTracker.DetectChanges();
    this.GetService<IStateManager>().GetEntriesToSave();

    try
    {
        ChangeTracker.AutoDetectChangesEnabled = false;

        foreach (var entry in ChangeTracker
            .Entries<CritiqueText>()
            .Where(e => Entry(e.Entity.Review).State == EntityState.Deleted))
        {
            entry.State = EntityState.Deleted;
        }
    }
    finally
    {
        ChangeTracker.AutoDetectChangesEnabled = true;
    }

    return base.SaveChanges(acceptAllChangesOnSuccess);
}

我接受了这一点,并以此为基础构建了基于属性的解决方案,您可以在test project repo中找到它。