8

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

interface ISoftDelete
{
  bool IsDeleted { get; set; }
}

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

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 的关系处于 'Deleted' 状态。给定多重约束,相应的 'Parent' 也必须处于 'Deleted' 状态。”}

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

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

4

1 回答 1

0

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

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

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

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

于 2012-10-13T06:16:23.973 回答