Linq Entity Framework通用过滤方法

时间:2010-07-10 17:26:37

标签: c# entity-framework linq-to-entities

我有一些方法可以对来自我的实体的数据执行标准过滤(使用Entity Framework v4)。

示例#1:

protected IQueryable<Database.Product> GetActiveProducts( ObjectSet<Database.Product> products ) {

    var allowedStates = new string[] { "Active" , "Pending" };

    return (
        from product in products
        where allowedStates.Contains( product.State )
            && product.Hidden == "No"
        select product
    );

}

示例#2:

protected IQueryable<Database.Customer> GetActiveProducts( ObjectSet<Database.Customer> customers ) {

    var allowedStates = new string[] { "Active" , "Pending" };

    return (
        from customer in customers
        where allowedStates.Contains( customer.State )
            && customer.Hidden == "No"
        select customer
    );

}

如您所见,这些方法与它们所操作的实体类型完全相同。我有超过10种这样的方法,一种用于我系统中每种类型的实体。

我试图理解我如何能够在任何实体类型中传递1个单一方法,并且如果存在2个字段/属性,则让它执行where子句。

我不在数据库中使用继承,因此就系统而言,每个实体类型都有“隐藏”和“状态”字段是巧合。

我的谷歌搜索告诉我它与使用Expression.Call()构建代码有关,但我的脑袋正在旋转!

2 个答案:

答案 0 :(得分:6)

我想说添加接口比弄乱表达式树反射更简单。 EF实体是部分类,因此您应该能够执行以下操作:

更新以包含类约束(请参阅Mark的评论)

public interface IHideable
{
  string State { get; }
  string Hidden { get; }
}

...

namespace Database
{
  public partial class Product : IHideable { }
  public partial class Customer : IHideable { }
}

...

protected IQueryable<T> GetActive<T>(ObjectSet<T> entities)
    where T : class, IHideable
{
  var allowedStates = new string[] { "Active" , "Pending" };    

  return (    
    from obj in entities
    where allowedStates.Contains(obj.State)
        && obj.Hidden == "No"
    select obj
  );
}  

答案 1 :(得分:3)

我想用IQueryable<T>作为泛型方法的输入参数类型做同样的事情。

我得到了“无法转换类型的运行时异常...... LINQ to Entities仅支持转换实体数据模型基元类型”。

经过一段时间我认识到,我忘了为泛型参数添加类约束。但是IQueryable<T>不需要具有类约束,它仍然需要在运行时解析类型。

如果没有这篇帖子,我需要几个小时。谢谢:))