LINQ - filtering a child collection

I would like to be able to query the parent objects and filter the contents of the child collection.

For example, I have a collection of OrderHeaders. I want to query this collection using LINQ to return all OrderHeaders, but I want some related OrderDetail strings to be included.

I prefer looking for a solution where I can do all this in a single LINQ statement.

This console application demonstrates this.

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

Thanks so much for any suggestions.

Floor

+8
c # linq
source share
1 answer

Try the following:

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

What then can be used like this:

 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(); } 
+16
source share

All Articles