【问题标题】:LINQ - filter child collectionLINQ - 过滤子集合
【发布时间】:2015-11-27 22:53:41
【问题描述】:

我希望能够查询父实体并过滤子集合的内容。

例如,我有一个 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; }
    }

}

非常感谢您的任何建议。

保罗

【问题讨论】:

  • 为什么痴迷于单个 LINQ 语句?
  • 我应该为这个问题提供更多背景信息。实际上,我正在使用 LINQ to Entity Framework,其中我使用动态表达式 API 生成 LINQ 语句(作为用户使用 UI 构建搜索条件的结果)。因此,我更愿意在一个 LINQ 语句上执行此操作。

标签: c# linq


【解决方案1】:

尝试以下方法:

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

【讨论】:

  • Any中的变量不是必须是“o”才能不改变父级中“o”的含义吗?
  • @ScottA.Lawrence 是的,你是对的——我的代码 sn-p 无法编译。答案已更新,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多