如何通过子属性查询LINQ中的对象集合?

时间:2009-10-15 19:47:53

标签: c# linq

我是linq的新手,无法编写两个简单的查询。出于某种原因,我无法绕过它。

它的结构简单:Order有OrderItems。每个orderItem都有一个productID。

我想:

  1. 获取订购productId 3的所有订单

  2. 获取在同一订单上订购productId 4和5的所有订单。

  3. 我已经尝试了很多方法。这两个查询位于小测试应用程序的底部。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace test
    {
        class Program
        {
            static void Main(string[] args)
            {
                OrderService svc = new OrderService();
    
                //find all orders that purchased ProductID 3
                IEnumerable<Order> data = svc.GetOrdersWithProduct(3);
    
                //find all orders that purchase product 4 AND 5
                IEnumerable<Order> data2 = svc.GetOrdersWithProduct(new int[] { 4, 5} );
            }
        }
    
        public class Order
        {
            public int OrderId { get; set; }
            public IEnumerable<OrderItem> Items { get; set; }
        }
    
        public class OrderItem
        {
            public int OrderItemId { get; set; }
            public int OrderId { get; set; }
            public int ProductId { get; set; }
        }
    
        public class OrderService
        {
            private static List<Order> GetTestData()
            {
                List<Order> orders = new List<Order>();
    
                //5 Orders, 3 items each (every orderitem has a unique product in this test set)
                int orderitemid = 1;
                int productid = 1;
                for (int orderid = 1; orderid < 6; orderid++)
                {
                    orders.Add(new Order
                    {
                        OrderId = orderid,
                        Items = new List<OrderItem> 
                                                    {
                                                        new OrderItem() { OrderId = orderid, OrderItemId = orderitemid++, ProductId = productid ++ },
                                                        new OrderItem() { OrderId = orderid, OrderItemId = orderitemid++, ProductId = productid ++ },
                                                        new OrderItem() { OrderId = orderid, OrderItemId = orderitemid++, ProductId = productid ++ }
                                                    }
                    });
    
                }
                return orders;
            }
    
            public IEnumerable<Order> GetOrdersWithProduct(int productId)
            {
                List<Order> orders = OrderService.GetTestData();
    
                // ??   not really what i want, since this returns only if all items are the same
                var result = orders.Where(o => o.Items.All(i => i.ProductId == productId));
    
                return result.ToList();
            }
    
            public IEnumerable<Order> GetOrdersWithProduct(IEnumerable<int> productIds)
            {
                List<Order> orders = OrderService.GetTestData();
    
                //??
                var result = orders.Where(o => o.Items.All(productIds.Contains(i => i.ProductId)));
    
                return result.ToList();
            }
        }
    }
    

4 个答案:

答案 0 :(得分:6)

我会这样做:

  1. 获取订购productId 3的所有订单

    var result = orders.Where(o => o.Items.Any(item => item.ProductId == 3));
    
  2. 获取订购productId 4和5的所有订单

    var result = orders.Where(o => o.Items.Any(item => item.ProductId == 4))
                       .Where(o => o.Items.Any(item => item.ProductId == 5));
    
  3. 或者:

    public static IEnumerable<Order> GetOrdersWithProduct(int id)
    {
        return orders.Where(o => o.Items.Any(item => item.ProductId == productId));
    }
    

    然后:

    var result1 = GetOrdersWithProduct(3);
    var result2 = GetOrdersWithProduct(4).Intersect(GetOrdersWithProduct(5));
    

    另一种选择:

    public static IEnumerable<Order> GetOrdersWithProducts(params int[] ids)
    {
        return GetOrdersWithProducts((IEnumerable<int>) ids);
    }
    
    public static IEnumerable<Order> GetOrdersWithProducts(IEnumerable<int> ids)
    {
        return orders.Where(o => !ids.Except(o.Items.Select(p => p.ProductId))
                                     .Any());
    }
    
    var result1 = GetOrdersWithProducts(3);
    var result2 = GetOrdersWithProduct(4, 5);
    

答案 1 :(得分:1)

没有Linq“语言集成查询”语法:

    public IEnumerable<Order> GetOrdersWithProduct(int productId)
    {
        List<Order> orders = OrderService.GetTestData();

        var result = orders.Where(o => o.Items.Any(i => i.ProductId == productId));

        return result.ToList();
    }

    public IEnumerable<Order> GetOrdersWithProduct(IEnumerable<int> productIds)
    {
        List<Order> orders = OrderService.GetTestData();

        var result = orders.Where(o => productIds.All(id => o.Items.Any(i => i.ProductId == id)));

        return result.ToList();
    }

似乎The Lame Duck正在进行“语言集成查询”版本,所以我不会这样做。

答案 2 :(得分:0)

检查这些:

1

from order in orders 
where order.Items.Exists(item => item.OrderItemId == 3)
select order
  1. 非常相似:

    从订单中订购 其中order.Items.Exists(item =&gt; item.OrderItemId == 3)&amp;&amp;
          order.Items.Exists(item =&gt; item.OrderItemId == 4) 选择订单

答案 3 :(得分:0)

    public IEnumerable<Order> GetOrdersWithProduct( int productId )
    {
        List<Order> orders = OrderService.GetTestData( );

        // ??   not really what i want, since this returns only if all items are the same
        //var result = orders.Where( o => o.Items.All( i => i.ProductId == productId ) );
        var result = orders.Where(o => o.Items.Any(ii => ii.ProductId == productId));

        return result.ToList( );
    }