2012-01-17 4 views
8

하위 엔터티를 쿼리하고 하위 컬렉션의 내용을 필터링 할 수 있기를 원합니다.LINQ - 하위 컬렉션 필터링

예를 들어 OrderHeaders 컬렉션이 있습니다. 모든 OrderHeaders를 반환하기 위해 LINQ를 사용하여이 컬렉션을 쿼리하려고하지만 관련된 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 문 강박 관념? –

+0

나는이 질문에 대해 더 많은 배경 지식을 제공해야한다. 실제 사실 나는 Entity Framework에 LINQ를 사용하고 있는데, Dynamic Expression API를 사용하여 LINQ 문을 생성하고 있습니다 (사용자가 UI로 검색 기준을 작성한 결과). 이 때문에 한 LINQ 문을 수행하는 것이 좋습니다. – P2l

답변

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

부모의 "o"의 의미를 변경하지 않으려면 모든 변수가 "o"가 아닌 다른 변수가 아니어야합니까? –

+0

@ ScottA.Lawrence 예, 맞습니다 - 제 코드 조각이 컴파일되지 않습니다. 답변 됨, 감사합니다. –

+0

@ rich-okelly 당신을 환영합니다 - 다행히 도울 수 있습니다. –