筛选集合的子集合
本文关键字:子集合 集合 筛选 | 更新日期: 2023-09-27 18:28:57
我有以下类:
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进行过滤,但保留在查询中添加更多过滤器的可能性
示例:我想要所有拥有SubExperience"x"或"y"的客户。请记住,SubExperience是集合(Experience)的子集合。然后我可以有新的过滤器。
我认为您正在寻找一种动态构建表达式的方法。您可以使用谓词生成器来完成这项工作。我最喜欢这个。
使用这个小宝石你可以做到这一点:
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
,而适合ICollection
的扩展方法Any
不接受Expression
,而是接受Func
,所以它不编译。
我对可恢复过滤器使用这样的模式,将过滤器定义为表达式
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。
假设您有一个列表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
}