1

如何过滤IsSoftDeleted掉这个 DbSet 中的项目?

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

4

2 回答 2

4

您的 What 类没有任何 IsSoftDeleted 属性,因此无需过滤。我将假设无论是从 BaseEntity 派生的。

主要问题是 IQueryable<T>.Where 实际上并不存在:它是一种扩展方法,扩展方法不能很好地处理动态类型。如果编译器可以看到一个类型实现了 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<BaseEntity>() 不同:这不起作用,因为 DbSet<BaseEntity> 和 DbSet<Whatever> 不兼容。只有使用 IQueryable 和其他带有“out”类型参数的接口才能执行此操作。

于 2011-12-06T23:06:43.807 回答
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是 type IQueryable<BaseEntity>,所以问题是,这个结果有多大用处,以及如何为派生实体应用进一步的过滤器,如Where(w => w.Name == "abc"). 至少,我无法通过制作settype来获得可编译的代码dynamic。我也不想失去所有强类型。

于 2011-12-06T23:07:19.267 回答