1

ご覧いただきありがとうございます。

バックグラウンド

C# で記述し、LINQ を使用してレポートのエンティティをクエリしています。このレポートには、基本的に次のような一連のエンティティがあります。

Customer{
       Name: "Bob",
       ProductsPurchased: ArrayOfChildEntities[{
             ProductId: 1,
             ProductTypeId: 5,
             ProductName: "FooBuzz"
          },
          {...},
          {...}]
}

ProductsPurchased製品タイプ ID を含む子エンティティの配列です。ユーザーがビューのフィルター リストから選択したタイプ ID の配列を渡すとします。

var ProductTypesToShow = [1, 3, 5];

そのため、返品された顧客ごとに、購入した、、、またはのタイプ1の製品のみを表示したいと思います。 顧客がタイプ、、またはの製品を 1 つも購入したことがない場合、その顧客オブジェクト全体を結果セットから削除する必要があります。35135

私が試したこと

私はこのようなものを使ってみました:

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

しかし、これは失敗します。私もさまざまなバージョンのIntersectand を試しましAnyたが、残念ながら、それらはすべて何らかの理由で失敗するか、必要なすべてのことを実行できません。

  1. 1タイプ、3、またはの製品を購入した顧客のみを選択します5

  2. 1それらの顧客のうち、タイプが 、3、またはではない製品をすべて削除5してから、データをビューに送り返します。

foreach最後に、最初のクエリで見つかったすべての顧客を反復し、製品を反復して製品タイプでフィルター処理するという怪物を書きましたが、これは容認できないほど遅くなりました (クエリごとに約 3 分!!)。

ここで明らかな何かが欠けているに違いないと感じています。どんな提案でも大歓迎です!

4

3 に答える 3

2

これは、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;
于 2013-04-09T16:09:41.677 に答える
2

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();

と の 2 つのプロパティを持つ匿名型の配列を返す必要がNameありProductsます。

于 2013-04-09T16:01:31.083 に答える
0
var results = customers
.Where(cust=>cust.ProductsPurchased.Any(ProductsToShow.Contains))
.Select(cust=>new{
           cust.Name,
           Purchases=cust.ProductsPurchased.Where(ProductsToShow.Contains)
    });
于 2013-04-09T16:09:13.117 に答える