2013-04-09 19 views
1

感謝您的期待!如何使用LINQ過濾和處理基於孩子和比較器之間相交值的結果?

背景

我正在用C#編寫,並使用LINQ查詢報表的實體。在這份報告中,我有一個實體的集合,基本上是這樣的:

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

ProductsPurchased是包含產品類別ID子實體的數組。比方說,我通過在類型ID的陣列,用戶從一個篩選器列表視圖選擇:

var ProductTypesToShow = [1, 3, 5];

因此,對於每一個客戶回來了,我想只顯示他們所購買的產品是類型1,35如果客戶從未購買過至少一種類型爲1,35的產品,則應從結果集中刪除整個客戶對象。

我已經試過

我一直在使用這樣的嘗試:

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

但這種失敗。我也嘗試過的IntersectAny各種版本,但遺憾的是他們都失敗的一個原因或其他,或者他們不能做所有我需要的東西:

  1. 只選擇誰購買那種產品的客戶1,35

  2. 在將這些數據發送回視圖之前,請刪除所有類型不是1,35的產品。

最後,我寫了一個foreach怪物,在迭代的初始查詢發現,所有的客戶,然後遍歷其產品按產品類型進行過濾,但是這是太慢(每個查詢約3分鐘!)。

我覺得我必須在這裏丟失一些明顯的東西。任何建議表示讚賞!

+0

我不知道如何使它沒有一些試驗工作,但你'Join'發揮呢? – Mikeb 2013-04-09 16:02:56

+0

我沒有但會。奇怪的是,我最近才發現'LINK'在LINQ中的強大程度。 – 2013-04-09 16:03:54

+1

也許您應該先創建SQL查詢,然後嘗試將其轉換爲LINQ to Entities? – MarcinJuraszek 2013-04-09 16:06:24

回答

2

這很難說,如果它與LINQ要去工作的實體,但我會嘗試一個:

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個屬性:NameProducts

+0

謝謝,我會試試這個。 – 2013-04-09 16:04:51

+0

謝謝,我將其轉換爲Lambda,但答案對我有用。 – 2013-04-09 16:58:13

0
var results = customers 
.Where(cust=>cust.ProductsPurchased.Any(ProductsToShow.Contains)) 
.Select(cust=>new{ 
      cust.Name, 
      Purchases=cust.ProductsPurchased.Where(ProductsToShow.Contains) 
    }); 
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; 
+0

是的,LINQ to Entities支持'Contains'並將其轉換爲'IN' SQL語句。 – MarcinJuraszek 2013-04-09 16:16:22

+0

謝謝。您添加關於什麼是延遲和什麼不是的評論是有幫助的。 – 2013-04-09 16:58:42