我想改变EF处理删除记录的方式。 它不应该删除数据库中的行,而应该填充一列(GCColumn左右)。
检索数据时,应始终过滤GCColumn IS NULL +您应用的过滤器。
任何人都知道这是否可以实现以及如何实现?
答案 0 :(得分:0)
在一个项目中,我们使用存储库模式进行数据库访问,每个实体都有自己的存储库。
它是一个多租户数据库,我们使用您要查找的过滤器类型来过滤当前用户可访问的实体,而不是过滤删除标志,但该方法可以类似地使用。
每个需要过滤的存储库都会获得一个过滤方法:
private Expression<Func<Order, bool>> RemoveDeleted
{
get
{
return order => order.GCColumn == null;
}
}
然后,为每个存储库方法添加一个表达式,如:
public override IEnumerable<Order> GetAll(Expression<Func<Order, bool>> expression)
{
expression = expression.And(RemoveDeleted);
return DbSet.Where(expression).ToList();
}
(扩展方法Add
来自一组ExpressionExtensions。)
现在,您可以使用以下表达式:
orderRepository.GetAll(x => x.ProductId == productId);
和
orderRepository.GetAll(x => x.OrderDate >= DateTime.Now.AddMonths(-1));
所以现在你的业务逻辑可以有很多方法使用相同的GetAll()方法,使用不同的过滤器,但不必关心'已删除'实体。但是您仍然有责任为每个存储库方法创建正确的过滤器。
如果删除标志不在所有实体中,但删除状态在另一个实体中注册,则可以执行以下操作:
private Expression<Func<Order, bool>> RemoveDeleted
{
get
{
return orderLine => orderLine.Order.GCColumn == null;
}
}
在此示例中,订单将被整体删除,而不是单独的行。
答案 1 :(得分:0)
除了上面的答案之外,考虑一下你们很多甚至所有实体都拥有这个GCC列的情况。
您可以从这些伪可删除实体的基础实体开始:
public abstract class PseudoDeletable
{
public DateTime GCColumn { get; set;}
}
并将实体定义为:
public class Order : PseudoDeletable
{
public int Id { get; set; }
public int ProductId { get; set; }
public DateTime OrderDate { get; set; }
// etc.
}
然后,您可以创建通用基础存储库
public class RepositoryBase<TEntity> where TEntity : PseudoDeletable
{
protected IDbSet<TEntity> DbSet { get; }
public RepositoryBase()
{
DbSet = context.Set<TEntity>();
}
private Expression<Func<TEntity, bool>> RemoveDeleted
{
get { return e => e.GCColumn == null; }
}
public virtual IEnumerable<TEntity> GetAll(Expression<Func<TEntity, bool>> expression)
{
expression = expression.And(RemoveDeleted);
return DbSet.Where(expression).ToList();
}
}
并派生了存储库,例如:
public class OrderRepository : RepositoryBase<Order>
{
}
然后可以像这样调用GetAll
方法:
new orderRepository().GetAll(x => x.ProductId == 1);
它将返回尚未删除的订单。
请注意,entity includes对于相关记录存在问题:如何仅包含未删除的相关实体,但这是因为您希望在数据库中保留“已删除”记录。