Entity framework 使用EntityFramework软删除(IShistorial列)
我正在使用一个数据库,在这个数据库中,设计者决定用一个IShistorial位列标记每个表。没有考虑正确的建模,也没有办法更改模式 在开发与导航属性交互的CRUD屏幕时,这会造成一些摩擦。我不能简单地拿一个产品,然后编辑它的实体集合,我必须手工写一个到处都是的历史记录,这让我发疯 添加也很可怕,因为到目前为止,我已经编写了所有手动检查,以查看添加是否只是软删除的,所以我可以切换IsHistoric,而不是添加重复的实体 我考虑过的三种选择是:Entity framework 使用EntityFramework软删除(IShistorial列),entity-framework,soft-delete,Entity Framework,Soft Delete,我正在使用一个数据库,在这个数据库中,设计者决定用一个IShistorial位列标记每个表。没有考虑正确的建模,也没有办法更改模式 在开发与导航属性交互的CRUD屏幕时,这会造成一些摩擦。我不能简单地拿一个产品,然后编辑它的实体集合,我必须手工写一个到处都是的历史记录,这让我发疯 添加也很可怕,因为到目前为止,我已经编写了所有手动检查,以查看添加是否只是软删除的,所以我可以切换IsHistoric,而不是添加重复的实体 我考虑过的三种选择是: 修改t4模板以包括IShistorial检查和同步
注意#2尽管LukeLed的回答迫使你进入一个非常糟糕的可怜人ORM、无图表的模式,但在技术上是正确的。问题在于,现在我需要从图中删除所有“已删除”的对象,然后对每个对象调用Delete方法。这并不能真正为我节省那么多的手工仪式编码。现在,我不再手工编写IsHistoric检查,而是收集已删除的对象并在其中循环。我在代码中使用通用存储库。你可以这样做:
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);
}
实体类可以很容易地标记为ISoftDelete,因为它们是部分的。需要在单独的文件中添加分部类定义:
public partial class MyClass : EntityObject, ISoftDelete
{
}
我相信您已经意识到,当您无法修改模式时,将不会有很好的解决方案。考虑到您不喜欢Repository选项(不过,我想知道您是否有点草率地放弃它),下面是我能想到的最好办法:
ObjectContext.SavingChanges
ObjectStateManager
搜索处于已删除状态的对象。如果它们具有Ishistorial
属性,则设置该属性,并将对象的状态更改为“修改”当涉及到关联/关系时,这可能会变得棘手,但我认为它或多或少符合您的要求。我使用存储库模式,代码与LukLed的类似,但我使用反射来查看Ishistorial属性是否存在(因为这是一种约定的命名约定):
公共类存储库,其中TEntityModel:EntityObject,new()
{
公共作废删除(TEntityModel实体)
{
//查看对象是否具有“Ishistorial”标志
if(typeof(TEntityModel).GetProperty(“Ishistorial”)!=null);
{
//执行软删除
var historicalProperty=entity.GetType().GetProperty(“Ishistorial”);
SetValue(实体,true,null);
}
其他的
{
//执行真正的删除
EntityContext.DeleteObject(实体);
}
EntityContext.SaveChanges();
}
}
用法简单地说是:
using (var fubarRepository = new Repository<Fubar>)
{
fubarRepository.Delete(someFubar);
}
使用(var fubarRepository=new Repository)
{
删除(someFubar);
}
当然,在实践中,您可以通过传递PK而不是实例化实体来扩展此线程以允许删除。我感觉到了您的痛苦,并将仔细监视此线程。希望你能得到答案!你为什么说它真的很差?您能解释一下吗?如果
T
是一个EntityObject
,那么它如何从接口ISoftDelete
继承?那不是多重继承吗(在.Net中是不允许的)?@Yaakow-Ellis:那是允许的。可以从一个类继承,但可以实现任意多个接口ISoftDelete
是接口。换句话说,ISoftDelete
定义了一个属性:IsDeleted
。没有一行代码表明classx
(T
)继承自ISoftDelete
。但是,如果X
有一个IsDeleted
属性,那么根据定义,任何实例化var i=new X()
都将返回(i是ISoftDelete)
为真?所以X
实现接口(通过遵循其约定),即使它不是从接口继承的?这是否使用反射?这样做会极大地影响性能吗?@YaakovEllis:您必须指定,您的实体通过添加部分类定义来实现isoftdelite。接口不是通过反射来解析的。所以像这样:?这怎么不是多重继承呢?
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();
}
}
using (var fubarRepository = new Repository<Fubar>)
{
fubarRepository.Delete(someFubar);
}