2012-01-17 34 views
8

Tôi muốn có thể truy vấn các thực thể mẹ và lọc nội dung của bộ sưu tập con.LINQ - bộ sưu tập bộ lọc trẻ em

Ví dụ: tôi có một bộ sưu tập của OrderHeaders. Tôi muốn truy vấn bộ sưu tập này bằng cách sử dụng LINQ để trả về tất cả các OrderHeaders, nhưng tôi chỉ muốn một số hàng OrderDetail có liên quan được bao gồm.

Tôi tốt nhất là tìm kiếm giải pháp mà tôi có thể thực hiện tất cả điều này trong một câu lệnh LINQ.

Ứng dụng bảng điều khiển sau đây minh họa điều này.

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; } 
    } 

} 

Rất cám ơn trước vì đã đề xuất.

Paul

+1

Tại sao nỗi ám ảnh với một tuyên bố LINQ đơn? –

+0

Tôi nên cung cấp thêm thông tin cơ bản cho câu hỏi này. Trong thực tế thực tế tôi đang sử dụng LINQ to Entity Framework nơi tôi đang tạo ra câu lệnh LINQ sử dụng API biểu thức động (như kết quả của người dùng xây dựng một tiêu chí tìm kiếm với một giao diện người dùng). Bởi vì điều này tôi muốn làm điều đó trên một tuyên bố LINQ. – P2l

Trả lời

16

Hãy thử như sau:

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") }); 

Đó là sau đó sử dụng được như vậy:

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

Biến không trong bất kỳ phải là một cái gì đó khác với "o" để không thay đổi ý nghĩa của "o" trong cha mẹ? –

+0

@ ScottA.Lawrence Có, bạn nói đúng - đoạn mã của tôi sẽ không biên dịch. Đã cập nhật câu trả lời, cảm ơn. –

+0

@ rich-okelly bạn được chào đón - rất vui được giúp đỡ. –

Các vấn đề liên quan