EntityFramework上的逻辑删除

时间:2013-02-19 13:27:14

标签: entity-framework

EntityFramework 上软删除的优雅方式是什么?我已将一个属性(数据库字段)标识为已删除,并始终在linq语句中使用此过滤器。

Foo Class  
  int NumberField  
  string Description 
  bool Deleted

contexts.Foos.Where(x=> !x.Deleted);

复杂查询不可行。

我只看了这些解决方案.. Link 1Link 2

任何帮助表示赞赏..

5 个答案:

答案 0 :(得分:2)

是的,这可以通过EF via pattern实现。 如果你使用Fascade / repository模式并通过该fascade访问每一次。

例如      所有存储库类上的接口实现可能如下所示:

 class MyRepositoryBase<T>....

    public IQueryable<T> ValidQuerySet  // this is not deleted check  Set

    {  get {  return Context.Set<T>().Where(t => t.deleted != true);
           }
    }

您将完全像访问原始DbSet一样进行访问。 EF将结合条件。

var myQuerySet = MyRespository<T>.ValidQuerySet.Where(t=>t.foo == "bar");

答案 1 :(得分:1)

您可能需要考虑在上下文类本身上创建存储库(如this site上所示),而不是直接查询您的上下文。您可以做的就是在查询记录时(例如,使用存储库的Filter<T>(Expression<Func<T, bool>> predicate)方法,您可以始终执行以下操作:

return Context.Set<Foo>().Where<Foo>(x => !x.Deleted).Where<Foo>(predicate).AsQueryable<Foo>();

如果您要在多个对象类型中实现该软删除,然后将其拉入抽象类(例如,将其称为SoftDeleteable),那么更好的是,然后使用Filter方法签名可以是:

public virtual IQueryable<T> Filter<T>(Expression<Func<T, bool>> predicate) where T : SoftDeletable

答案 2 :(得分:0)

你可能不会喜欢我的答案,但我能想到的“不那么痛苦”的方式需要大量的存储过程:每个实体1个,而你所做的只是存在UPDATE foo Deleted = True。我的通常看起来像这样

PROCEDURE [dbo].[SP_Address_UnSet]
    @ID bigint
AS
BEGIN
    DECLARE @IsInactive bit

    SELECT @IsInactive = IsInactive
    FROM [Address]
    WHERE AddressID = @ID

    IF (0 = @@ROWCOUNT)
        RETURN -1

    -- implicit else

    IF (1 = @IsInactive)
        RETURN 0

    -- implicit else

    UPDATE [Address]
    SET IsInactive = 1
    WHERE AddressID = @ID

    RETURN @@ROWCOUNT -- should be 1
END

然后在该SP的每个实体地图上。

你可以拥有1个单独的SP,并将表名作为参数传递,但由于你不能通过动态查询直接在T-SQL中使用它,你必须构建子执行(并且担心avout SQL注入! !)

Exec('SELECT * FROM ' + @tableName)

答案 3 :(得分:0)

Global Query Filters (EF Core)Entity Framework Interceptors (EF 6+)是EntityFramework上添加的新功能,用于解决此类问题。

答案 4 :(得分:-1)

我发现以这种方式进行“软删除”非常痛苦:

  1. 当你进行数据访问时,你必须记住这个标志。 是的,你可以将它包装在一些存储库模式中,但你仍然可以 到处都有。
  2. 你的桌子很快被“删除”填满 条目,并使报告,分析效率低下。
  3. 我建议您只需将“已删除”条目放入不同的表格或数据库中,从长远来看,这将节省您的时间。