实体框架覆盖保存对软删除实体的更改

时间:2017-03-08 17:47:19

标签: c# entity-framework entity-framework-6

我正在尝试覆盖我的数据库上下文中的Savechanges以将我的entites标记为SoftDeleted。

我有一个ISoftDeletable基础,我在我的实体类中重写

public interface IsoftDeletable
{
    public bool IsDeleted {get; set;}
}

然后在我的上下文中

public override int SaveChanges()
{
    foreach (var entry in ChangeTracker.Entries()
              .Where(p => p.State == EntityState.Deleted))
        SoftDelete(entry);

    return base.SaveChanges();
}

private void SoftDelete(DbEntityEntry entry)
{
   var entity = entry.Entity as ISoftDeltable;
   entity.IsDeleted = true;
   entry.State = EntityState.Modified;
}

如果我删除了一个实体,它会被软删除,但问题是如果该实体具有Cascade删除的子集合,则实例框架不会跟踪子集合,并且它们不会被标记为已删除。

一个简单的解决方案是在删除发生之前急切地加载要删除的实体的所有子集合,以便Ef跟踪子节点中的更改并软删除它们但这是一个"劈"我想避免。在删除发生之前,很难记住实体之间的所有关系并急切加载所有内容。如果模型发生变化,也很难保持这种状态。

有没有更好的方法来实现这种功能?

编辑1:我不明白这个问题可能与this

相似

1 个答案:

答案 0 :(得分:2)

我会尝试在DBMS方面,而不是在应用程序方面。

我会假设你有MS SQL Server。 MS SQL Server支持“级联更新”,其方式与“级联删除”类似。这意味着如果你有一个带有主键PersonID的Person表和一个Car表,其中有一个PersonID外键引用Person表中的PersonID,那么无论何时更改Person for PersonID中的值,相关记录中的外键都是Car也会更新此值。

所以在你的情况下,我要做的是修改外键。假设你有两张桌子:

人:( PersonId,Name,Age,IsDeleted)
车:( CarId,Make,Model,PersonId,IsDeleted)

PersonID是人物中的PK,而CarId是Car中的PK。而不是使Car.PersonId成为引用Person.PersonId的FK,而是创建复合外键:(Car.PersonId,Car.IsDeleted)=> (Person.PersonId,Person.IsDeleted)并且为此复合FK指定“on update cascade”选项。这样每当你改变Person.PersonId(你永远不会)或Person.IsDeleted时,新值将被级联更新到相应的Car.PersonId(由于Person.PersonId不会改变,因此不再级联更新)和Car.IsDeleted。