我如何使用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];

因此,对于每个返回的客户,我只想显示他们购买的类型为135的产品。如果客户从未购买过至少一个135类型的产品,则应从结果集中删除整个客户对象。

What I have try

我试过这样做:

var customers = db.Customers.Where(c => c.ProductsPurchased.Select(p => ProductTypesToShow.Contains(p.ProductTypeId));

但是这失败了。我也尝试了各种版本的IntersectAny,但不幸的是,他们都失败了,因为这样或那样的原因,或者他们没有做我需要的所有事情:

  1. 只选择购买135类型产品的客户。

  2. 在这些客户中,在将数据发送回视图之前,删除所有非1, 35类型的产品。

最后,我写了一个foreach怪物,迭代在初始查询中找到的所有客户,然后迭代他们的产品以按产品类型过滤,但这太慢了(每次查询大约3分钟!!)。

我觉得我一定错过了一些明显的东西。任何建议都很感激!

我如何使用LINQ来过滤和操作基于子节点和比较器之间相交的值的结果

很难说它是否会与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();

它应该返回一个匿名类型的数组,具有两个属性:NameProducts

我在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)
    });