我如何使用LINQ来过滤和操作基于子节点和比较器之间相交的值的结果
本文关键字:之间 比较器 结果 子节点 LINQ 何使用 过滤 操作 | 更新日期: 2023-09-27 18:08:21
感谢您的关注!
<标题> 的背景我正在用c#编写,并使用LINQ来查询报告的实体。在这个报告中,我有一组实体,它们基本上是这样的:
Customer{
Name: "Bob",
ProductsPurchased: ArrayOfChildEntities[{
ProductId: 1,
ProductTypeId: 5,
ProductName: "FooBuzz"
},
{...},
{...}]
}
ProductsPurchased
是包含产品类型id的子实体数组。假设我传入一个id类型的数组,它是用户从视图中的过滤器列表中选择的:
var ProductTypesToShow = [1, 3, 5];
因此,对于每个返回的客户,我只想显示他们购买的类型为1
、3
或5
的产品。如果客户从未购买过至少一个1
、3
或5
类型的产品,则应从结果集中删除整个客户对象。
What I have try
我试过这样做:
var customers = db.Customers.Where(c => c.ProductsPurchased.Select(p => ProductTypesToShow.Contains(p.ProductTypeId));
但是这失败了。我也尝试了各种版本的Intersect
和Any
,但不幸的是,他们都失败了,因为这样或那样的原因,或者他们没有做我需要的所有事情:
只选择购买
1
、3
或5
类型产品的客户。在这些客户中,在将数据发送回视图之前,删除所有非
1
,3
或5
类型的产品。
最后,我写了一个foreach
怪物,迭代在初始查询中找到的所有客户,然后迭代他们的产品以按产品类型过滤,但这太慢了(每次查询大约3分钟!!)。
我觉得我一定错过了一些明显的东西。任何建议都很感激!
标题>很难说它是否会与LINQ to Entities一起工作,但我会尝试那个:
var results = (from c in customers
select new
{
Name = c.Name,
Products = c.ProductsPurchased.Where(p => ProductTypesToShow.Contains(p.ProductTypeId))
} into c2
where c2.Products.Any()
select new
{
Name = c2.Name,
Products = c2.Products.ToArray()
}).ToArray();
它应该返回一个匿名类型的数组,具有两个属性:Name
和Products
。
我在LinqToSql中就是这样做的。我不确定LinqToEntities是否支持Contains。
List<int> ProductTypesToShow = new List<int>() {1,3,5};
IQueryable<Product> productQuery = dc.Products
.Where(p => ProductTypesToShow.Contains(p.ProductTypeId)); //deferred
var customerProductQuery =
from c in dc.Customers
join p in productQuery on c.CustomerID equals p.CustomerID into g //groupjoin!
where g.Any()
select new {Customer = c, Products = g.ToList()}; //customers with their products. deferred
List<Customer> result = new List<Customer>();
foreach(var pair in customerProductQuery) //query executed
{ //manual result shaping
Customer resultItem = pair.Customer;
resultItem.Products = pair.Products;
result.Add(resultItem);
}
return result;
var results = customers
.Where(cust=>cust.ProductsPurchased.Any(ProductsToShow.Contains))
.Select(cust=>new{
cust.Name,
Purchases=cust.ProductsPurchased.Where(ProductsToShow.Contains)
});