使用EntityFramework软删除(IsHistorical列)

Joh*_*ell 9 entity-framework soft-delete

我正在使用一个数据库,设计人员决定用IsHistorical位列标记每个表.没有考虑正确的建模,我无法改变架构.

在开发与导航属性交互的CRUD屏幕时,这会引起一些摩擦.我不能简单地拿一个产品然后编辑它的EntityCollection我必须手动编写IsHistorical检查到处都是它让我疯了.

添加也很可怕,因为到目前为止我已经编写了所有手动检查以查看添加是否只是软删除,因此我可以切换IsHistoric而不是添加重复的实体.

我考虑过的三个选项是:

  1. 修改t4模板以包括IsHistorical检查和同步.

  2. 拦截ObjectContext中的删除和添加,切换IsHistorical列,然后同步对象状态.

  3. 订阅AssociationChanged事件并在那里切换IsHistorical列.

有没有人有这方面的经验或者可以推荐最无痛的方法?

注意:是的,我知道,这是不好的建模.我已经阅读了有关软删除的相同文章.它很臭,我必须处理这个要求,但我这样做.我只想要最轻松的处理软删除的方法,而无需为我的数据库中的每个导航属性编写相同的代码.

注意#2 LukeLed的答案在技术上是正确的,虽然迫使你陷入一个非常糟糕的穷人ORM,无图形,模式.问题在于,现在我需要从图中删除所有"已删除"的对象,然后在每个对象上调用Delete方法.那不是真的会省去那么多手工仪式编码.现在我没有编写手动IsHistoric检查,而是收集已删除的对象并循环遍历它们.

Luk*_*Led 8

我在我的代码中使用通用存储库.你可以这样做:

public class Repository<T> : IRepository<T> where T : EntityObject
{
    public void Delete(T obj)
    {
        if (obj is ISoftDelete)
            ((ISoftDelete)obj).IsHistorical = true
        else
            _ctx.DeleteObject(obj);
    }
Run Code Online (Sandbox Code Playgroud)

您的List()方法也会通过IsHistorical进行过滤.

编辑:

ISoftDelete 接口:

public interface ISoftDelete
{
    bool IsHistorical { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

实体类可以很容易地标记为ISoftDelete,因为它们是部分的.部分类定义需要添加到单独的文件中:

public partial class MyClass : EntityObject, ISoftDelete
{

}
Run Code Online (Sandbox Code Playgroud)


Cra*_*ntz 5

我相信你知道,当你无法修改架构时,这个问题不会有很好的解决方案.鉴于你不喜欢Repository选项(不过,我想知道你是不是有点急于解雇它),这是我能想到的最好的:

  1. 处理 ObjectContext.SavingChanges
  2. 当该事件触发时,通过ObjectStateManager查找已删除状态的对象进行搜索.如果它们具有IsHistorical属性,请设置该属性,并将对象的状态更改为已修改.

当涉及到协会/关系时,这可能会变得棘手,但我认为它或多或少会做你想要的.