2012-01-17 114 views
8

我想查詢父實體並篩選子集合的內容。LINQ - 篩選子集合

例如,我有一個OrderHeaders的集合。我想用LINQ來查詢這個集合來返回所有的OrderHeaders,但我只想要包含一些相關的OrderDetail行。

我最好尋找一個解決方案,我可以在單個LINQ語句中完成所有這些。

以下控制檯應用程序演示了這一點。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace LINQ 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<OrderHeader> orders = GetOrderHeaders(); 

      var filteredOrders = from p in orders 
           where p.Detail.Where(e => e.StockCode == "STK2").Count() > 0 
           select p; 

      foreach (var order in filteredOrders) 
      { 
       Console.WriteLine("Account {0} ", order.AccountCode); 

       foreach (var detail in order.Detail) 
       { 
        Console.WriteLine("StockCode {0}, Quantity {1}", detail.StockCode, detail.Quantity); 
       } 

       Console.WriteLine(); 
      } 

      // The above will return the following: 
      // Account CUST1 
      // StockCode STK1, Quantity 1 
      // StockCode STK2, Quantity 2 
      // 
      // Account CUST2 
      // StockCode STK2, Quantity 1 
      // StockCode STK4, Quantity 2 

      // How can I get the following? 
      // Account CUST1 
      // StockCode STK2, Quantity 2 
      // 
      // Account CUST2 
      // StockCode STK2, Quantity 1 

      Console.ReadLine(); 
     } 

     public static List<OrderHeader> GetOrderHeaders() 
     { 
      List<OrderHeader> orders = new List<OrderHeader>(); 

      OrderHeader header = 
       new OrderHeader { 
        AccountCode = "CUST1", 
        Detail = new List<OrderDetail>()}; 
      header.Detail.Add(
       new OrderDetail { StockCode = "STK1", Quantity = 1 }); 
      header.Detail.Add(
       new OrderDetail { StockCode = "STK2", Quantity = 2 }); 
      orders.Add(header); 

      header = 
       new OrderHeader 
       { 
        AccountCode = "CUST2", 
        Detail = new List<OrderDetail>() 
       }; 
      header.Detail.Add(
       new OrderDetail { StockCode = "STK2", Quantity = 1 }); 
      header.Detail.Add(
       new OrderDetail { StockCode = "STK4", Quantity = 2 }); 
      orders.Add(header); 

      return orders; 
     } 
    } 

    public class OrderHeader 
    { 
     public string AccountCode { get; set; } 
     public List<OrderDetail> Detail {get; set;} 
    } 

    public class OrderDetail 
    { 
     public string StockCode { get; set; } 
     public int Quantity { get; set; } 
    } 

} 

非常感謝您的任何建議。

保羅

+1

爲什麼用一個單一的LINQ語句癡迷? – 2012-01-17 14:36:46

+0

我應該給這個問題更多的背景。實際上,我正在使用LINQ to Entity Framework,在那裏我使用Dynamic Expression API生成LINQ語句(作爲用戶使用UI建立搜索條件的結果)。正因爲如此,我寧願在一個LINQ語句中這樣做。 – P2l 2012-01-17 14:55:17

回答

16

嘗試以下操作:

var filtered = orders 
    .Where(o => o.Detail.Any(d => d.StockCode == "STK2")) 
    .Select(o => new { Order = o, Details = o.Detail.Where(d => d.StockCode == "STK2") }); 

,然後可用就像這樣:

foreach (var entity in filtered) 
{ 
    Console.WriteLine("Account {0} ", entity.Order.AccountCode); 
    foreach (var detail in entity.Details) 
    { 
     Console.WriteLine("StockCode {0}, Quantity {1}", detail.StockCode, detail.Quantity); 
    } 
    Console.WriteLine(); 
} 
+1

Any中的變量是否必須是「o」以外的某個變量,以免在父級中更改「o」的含義? – 2013-01-16 20:51:56

+0

@ ScottA.Lawrence是的,你是對的 - 我的代碼片段不會編譯。答覆更新,謝謝。 – 2013-01-17 09:15:55

+0

@ rich-okelly歡迎您 - 很高興提供幫助。 – 2013-01-17 17:21:20