9

我正在使用一个数据库,设计师决定用 IsHistorical 位列标记每个表。没有考虑适当的建模,也无法更改架构。

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

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

我考虑过的三个选项是:

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

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

  3. 订阅 AssociationChanged 事件并在此处切换 IsHistorical 列。

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

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

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

4

3 回答 3

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);
    }

您的List()方法也会按 IsHistorical 过滤。

编辑:

ISoftDelete界面:

public interface ISoftDelete
{
    bool IsHistorical { get; set; }
}

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

public partial class MyClass : EntityObject, ISoftDelete
{

}
于 2009-12-21T22:51:01.470 回答
5

As I'm sure you're aware, there is not going to be a great solution to this problem when you cannot modify the schema. Given that you don't like the Repository option (though, I wonder if you're not being just a bit hasty to dismiss it), here's the best I can come up with:

  1. Handle ObjectContext.SavingChanges
  2. When that event fires, trawl through the ObjectStateManager looking for objects in the deleted state. If they have an IsHistorical property, set that, and changed the state of the object to modified.

This could get tricky when it comes to associations/relationships, but I think it more or less does what you want.

于 2009-12-22T13:21:36.577 回答
0

I use the repository pattern also with similar code to LukLed's, but I use reflection to see if the IsHistorical property is there (since it's an agreed upon naming convention):

public class Repository<TEntityModel> where TEntityModel : EntityObject, new() 
{
       public void Delete(TEntityModel entity)
        {
            // see if the object has an "IsHistorical" flag
            if (typeof(TEntityModel).GetProperty("IsHistorical") != null);
            {
                // perform soft delete
                var historicalProperty = entity.GetType().GetProperty("IsHistorical");
                historicalProperty.SetValue(entity, true, null);
            }
            else
            {
                // perform real delete
                EntityContext.DeleteObject(entity);
            }

            EntityContext.SaveChanges();                
        }
}

Usage is then simply:

using (var fubarRepository = new Repository<Fubar>)
{
   fubarRepository.Delete(someFubar); 
}

当然,在实践中,您可以通过传递 PK 而不是实例化实体等来扩展它以允许删除。

于 2013-05-02T15:00:07.627 回答