简体   繁体   English

Linq Entity Framework通用过滤方法

[英]Linq Entity Framework generic filter method

I have some methods which perform a standard filter on data from my Entities (using Entity Framework v4). 我有一些方法对我的实体的数据执行标准过滤(使用Entity Framework v4)。

Example #1: 示例#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
    );

}

Example #2: 示例#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
    );

}

As you can see, these methods are identical apart from the Entity types they operate on. 如您所见,这些方法与它们运行的​​实体类型完全相同。 I have more than 10 of these types of methods, one for each type of Entity in my system. 我有超过10种这样的方法,一种用于我系统中的每种类型的实体。

I am trying to understand how I could have 1 single method for which I could pass in any Entity type, and have it perform the where clause if the 2 fields/properties exist. 我试图理解我如何能够在任何实体类型中传递1个单一方法,并且如果存在2个字段/属性,则让它执行where子句。

I do not use Inheritance in the database, so as far as the system goes, it is coincidental that each of the Entity types have the fields "Hidden" and "State". 我不在数据库中使用继承,因此就系统而言,每个实体类型都有“隐藏”和“状态”字段是巧合。

My Googling tells me it has something to do with building code using Expression.Call() but my head is now spinning! 我的谷歌搜索告诉我它与使用Expression.Call()构建代码有关,但我的头现在正在旋转!

I'd say adding interfaces is a simpler option than messing with the expression tree or reflection. 我想说添加接口比弄乱表达式树反射更简单。 EF entities are partial classes, so you should be able to do something like: EF实体是部分类,因此您应该能够执行以下操作:

Updated to include class constraint (see Mark's comment) 更新为包含类约束(请参阅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
  );
}  

I wanted to do the same thing with IQueryable<T> as an input parameter type for the generic method. 我想用IQueryable<T>作为泛型方法的输入参数类型做同样的事情。

I got the runtime exception of "Unable to cast the type.... LINQ to Entities only supports casting Entity Data Model primitive types". 我得到了“无法转换类型的运行时异常.... LINQ to Entities仅支持转换实体数据模型基元类型”。

After some time I recognized, I forgot to add the class constraint for the generic parameter. 经过一段时间我认识到,我忘了为泛型参数添加类约束。 However IQueryable<T> does not require to have the class constraint, it still needs that to resolve the types at runtime. 但是IQueryable<T>不需要具有类约束,它仍然需要在运行时解析类型。

It would have taken me hours, without this post. 如果没有这篇帖子,我需要几个小时。 Thanks :) 谢谢 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM