C# 集合的筛选器子集合

C# 集合的筛选器子集合,c#,linq,entity-framework,C#,Linq,Entity Framework,我有以下课程: class Customer { public int IdCustomer {get; set} public string Name {get; set;} public virtual ICollection<Expertise> Expertises {get; set;} } class Expertise { public int IdExpertise {get; set;} public string Descripti

我有以下课程:

class Customer
{
   public int IdCustomer {get; set}
   public string Name {get; set;}
   public virtual ICollection<Expertise> Expertises {get; set;}
}

class Expertise
{
   public int IdExpertise {get; set;}
   public string Description {get; set;}
   public virtual ICollection<SubExpertise> SubExpertises {get; set;}
}

class SubExpertise
{
   public int IdSubExpertise { get; set;}
   public int IdExpertise {get; set;}
   public string Description {get; set;}
   public virtual Expertise Expertise {get; set;}
}
如何使用IQueryable筛选子专家,并保持筛选条件?基本上,我希望按子专业知识进行筛选,但保留在查询中添加更多筛选器的可能性

示例:我希望所有具有子专业知识“x”或“y”的客户。请记住,子专业知识是集合专业知识的子集合。之后我可以有新的过滤器。

假设您有一个客户列表

您可以在IsXOrY:中添加任何筛选条件,并且应该重命名它

bool IsXOrY(SubExpertise subExpertise)
{
    check if the SubExpertise is 'x' or 'y'
    check if the SubExpertise meets other criteria
    return true if this SubExpertise meets all your criteria
}

对于可恢复过滤器,我使用这样的模式,将过滤器定义为表达式

public static class SubExpertiseFilter
{
    public static Expression<SubExpertise, bool> XorY =
         se => se.Description == "X" || se.Description == "Y";

}
如果我想应用它:

public IQueryable<Expertise> ApplyXorYFilter(IQueryable<Expertise> expertises, bool appyXorY)
{
    if(applyXorY)
    {
        expertises = expertises.Any(e => e.Subexpertises.AsQueryable().Any(SubExpertiseFilter.XorY);
    }

    return expertises;
}
或者直接在你需要的地方做


AsQueryable需要在另一个表达式中使用该表达式,以便EF满意它,否则编译器需要一个函数,而EF无法将其转换为SQL。

我认为您正在寻找一种动态构建表达式的方法。您可以使用谓词生成器来完成这项工作。我最喜欢的是

使用这个小宝石,你可以做到:

var pred = PredicateBuilder.Create<SubExpertise>(s => s.Description == "x");
pred = pred.Or(s => s.Description == "y");

var customers = db.Customers
                  .Where(c => c.Expertises
                               .Any(e => e.SubExpertises.AsQueryable()
                                          .Any(pred)));

e、 子专家必须强制转换为IQueryable,因为它的编译时类型是ICollection,而适合ICollection的扩展方法Any不接受表达式而是Func,因此它不会编译。

IQueryable背后是什么?它是否需要是实体框架支持的条件?是。基本上,我有很多来自接口过滤器的条件,我会检查使用了哪些条件。这不适用于EF LINQ查询。它会抱怨IsXOrY不能被翻译成SQL。
var pred = PredicateBuilder.Create<SubExpertise>(s => s.Description == "x");
pred = pred.Or(s => s.Description == "y");

var customers = db.Customers
                  .Where(c => c.Expertises
                               .Any(e => e.SubExpertises.AsQueryable()
                                          .Any(pred)));