使用关联覆盖实体删除

Posted

技术标签:

【中文标题】使用关联覆盖实体删除【英文标题】:Overriding entity deletion with associations 【发布时间】:2012-09-23 12:33:29 【问题描述】:

我正在尝试通过覆盖DbContext.SaveChanges() 方法并撤消删除任何实现我的ISoftDelete 接口的实体来在我的项目中实现软删除功能。

interface ISoftDelete

  bool IsDeleted  get; set; 

SaveChanges() 方法中,我为每个处于“已删除”状态并实现ISoftDelete 的条目调用我的SoftDelete() 方法。:

var entries = this.ChangeTracker.Entries().Where(x => (x.State == EntityState.Deleted) && x.Entity is ISoftDelete)
                    .ToList();
                entries.ForEach(SoftDelete);

我的SoftDelete()方法如下:

private void SoftDelete(DbEntityEntry entry)

    if (entry.State == EntityState.Deleted && entry.Entity is ISoftDelete)
    
        entry.Reload();
        var entity = (ISoftDelete)entry.Entity;
        entity.IsDeleted = true;
        entry.State = EntityState.Modified;
    

这将完美地工作,直到我遇到一个与其他事物具有一对一关联的实体。此时会抛出异常并出现此错误:

"来自 'ChildParent' AssociationSet 的关系在 “已删除”状态。给定多重约束,对应的 'Parent' 也必须处于 'Deleted' 状态。"

有没有办法获取该实体的所有关联并同时更改它们的已删除状态?

我已经尝试获取对实际关联实体的引用,但实体的 EntityState 设置为 Unchanged 而不是 Deleted

【问题讨论】:

我认为关联本身被标记为已删除(关联在 EF 中被视为单独的对象),而不是相关实体。现在,当 EF 尝试删除关联时,它不能,因为相关实体未标记为已删除。我假设外键不可为空,因此删除实体需要删除相关实体(级联删除)。您可以查看此线程:***.com/questions/10300156/…。它可能会有所帮助,因为它显示了如何获取相关对象。 对获取相关对象很有帮助,谢谢。但是,当尝试更改其中一个关系的状态时,我收到一个奇怪的错误,提示“如果关系的一端是 KeyEntry,则无法更改关系的状态。” 你看过this workaround吗? 【参考方案1】:

一般情况下,您需要先软删除父子关系中的子项。从最顶层的父级开始,然后递归遍历子级。标记访问的每个项目,以便您可以跟踪它是否已被软删除(以防反向引用)。

如果您有“业务对象”概念,您可以添加ChildsParent 属性以便于导航。否则,您将不得不在每个具有非平凡子关系的父级上“手动编码”。

还要注意,使用一个 LINQ 语句,您无法控制实际的遍历。

我知道上面的工作似乎很多,但考虑一下如何在 EF 中设计一种机制来自动推断所需的关系信息?!你最终会正确地做这样的事情。

【讨论】:

以上是关于使用关联覆盖实体删除的主要内容,如果未能解决你的问题,请参考以下文章

删除与基于视图的实体具有一对多关联的实体对象

如何使用 Spring Data JPA(Hibernate) 跨映射表过滤关联实体?

删除两个实体之间的关系 MagicalRecord

EFCode First:删除具有两个实体关联的值对象

Entity Framework 6 Recipes 2nd Edition(12-5)译 -> 自动删除相关联实体

如何使用 Entity Framework 自动过滤掉软删除的实体?