过滤集合的子集合

时间:2014-11-04 12:13:36

标签: 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 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过滤 SubExpertise ,并保持过滤条件?基本上我想通过 SubExpertise 过滤,但保留在查询中添加更多过滤器的可能性

示例:我想要所有拥有SubExpertise&#39; x&#39;或者&#39; y&#39;。请记住,SubExpertise是集合的子集合(专业知识)。在此之后我可以使用新的过滤器。

3 个答案:

答案 0 :(得分:1)

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

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

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.SubExpertises必须转换为IQueryable,因为它的编译时类型为ICollection,并且符合Any的扩展方法ICollection不接受<{1}}但是Expression,因此无法编译。

答案 1 :(得分:0)

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

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;
}

或者只是在需要它的地方进行内联。

&#34; AsQueryable&#34;需要在另一个表达式中使用表达式,以便EF对它感到满意,否则编译器需要一个函数,而EF不能转化为SQL。

答案 2 :(得分:-1)

假设您有一个列表customers

var filteredCustomers = from customer in customers
                        where customer.Expertises.Any(e => e.Subexpertises.Any(s => IsXOrY(s)))
                        select customer;

您可以在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
}