从DbContext Set()中筛选出软删除

时间:2011-12-06 22:42:36

标签: c# asp.net entity-framework-4 dbcontext soft-delete

如何从此DbSet中过滤出IsSoftDeleted个项目?

var type = GetTypeFromString("Whatever");
var whatevers = Set(type);

方法

public dynamic Set(Type type)
{
    var set = dbContext.Set(type);
    return set;
}

模型

public class Whatever : BaseEntity
{
    public virtual string Name { get; set; }
}
public class BaseEntity
{
   public virtual int Id { get; set; }
   public virtual bool? IsSoftDeleted { get; set; }
}

编辑:忘记显示来自Whatever

BaseEntity

2 个答案:

答案 0 :(得分:4)

您的Whatever类没有任何IsSoftDeleted属性,因此无需过滤。我将假设从BaseEntity派生出什么。

主要问题是IQueryable< T>。实际上并不存在:它是一个扩展方法,并且扩展方法对动态类型不起作用。如果编译器可以看到类型实现IQueryable< T>,则可以键入var.Where(...)并让编译器将其解析为System.Linq.Queryable.Where(var,...)。由于该示例中的类型是动态的,因此编译器不知道它实现了IQueryable,并且当您尝试调用Where时会报告错误。

您可以将DbSet强制转换为IQueryable< BaseEntity> (只要Type有BaseEntity作为基类),并调用任何过滤器。你真的使用动态类型功能吗?如果没有,您还可以考虑删除自定义Set函数,并使用默认的DbContext.Set函数。

var query = (from e in (IQueryable<BaseEntity>)dbContext.Set(type)
             where e.IsSoftDeleted != true
             select e);

注意:这与与使用dbContext.Set(type)相同.Cast&lt; BaseEntity&gt;():这不起作用,因为DbSet&lt; BaseEntity&gt;和DbSet&lt; Whatever&gt;是不相容的。只有IQueryable和其他具有“out”类型参数的接口才能执行此操作。

答案 1 :(得分:3)

问题是Set(Type type)会返回非通用DbSet。要应用过滤器,您必须将其强制转换为通用IQueryable<T>

var set = ((IQueryable<BaseEntity>)dbContext.Set(type))
              .Where(be => be.IsSoftDeleted.HasValue && !be.IsSoftDeleted.Value);

仅当type来自BaseEntityBaseEntity本身时才有效,否则您将获得运行时异常。

结果set的类型为IQueryable<BaseEntity>,因此问题是,此结果的用途以及如何为Where(w => w.Name == "abc")等派生实体应用更多过滤器。至少,通过制作set类型的dynamic,我无法获得可编译的代码。我也不想失去所有强烈的打字。