2012-01-17 127 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