LINQ查询 - 仅从子集合中获取Order和MAX Date

时间:2012-11-07 10:25:04

标签: c# linq entity-framework

我正在尝试获取一个列表,该列表在父级和子级(1- *)实体集合模型的标签中显示2个值。

我有3个实体:

  1. [客户]:CustomerId,姓名,地址,......
  2. [订单]:OrderId,OrderDate,EmployeeId,Total,...
  3. [ OrderStatus ]:OrderStatusId,StatusLevel,StatusDate,...
  4. 客户可以有多个订单,而订单可以有多个 OrderStatus ,即 [客户] 1 - * [订单] 1 - * [订单状态]

    鉴于CustomerId,我想得到该订单的所有订单(只是OrderId)和LATEST(MAX?)OrderStatus.StatusDate。

    我尝试了几次尝试,但似乎可以得到我想要的结果。

    private IQueryable<Customer> GetOrderData(string customerId)
    {
         var ordersWithLatestStatusDate = Context.Customers
    
         // Note: I am not sure if I should add the .Expand() extension methods here for the other two entity collections since I want these queries to be as performant as possible and since I am projecting below (only need to display 2 fields for each record in the IQueryable<T>, but thinking I should now after some contemplation.
    
         .Where(x => x.CustomerId == SelectedCustomer.CustomerId)
         .Select(x => new Custom 
         {
             CustomerId = x.CustomerId,
             ...
             // I would like to project my Child and GrandChild Collections, i.e. Orders and OrderStatuses here but don't know how to do that. I learned that by projecting, one does not need to "Include/Expand" these extension methods.  
         });
         return ordersWithLatestStatusDate ;
    }
    

    ----更新1 ----

    在用户:lazyberezovsky的出色解决方案之后,我尝试了以下方法:

    var query = Context.Customers
                .Where(c => c.CustomerId == SelectedCustomer.CustomerId)
                .Select(o => new Customer 
                { 
                    Name = c.Name, 
                    LatestOrderDate = o.OrderStatus.Max(s => s.StatusDate) 
                });
    

    在我最初的帖子中,我没有正确地粘贴所有内容,因为它主要来自内存,并且当时没有确切的代码供参考。我的方法是一个强类型的IQueryabled,我需要它返回一个类型为T的项的集合,因为我必须通过一个具有IQueryable查询作为其参数之一的刚性API中的约束。我知道我可以通过使用扩展方法.Expand()和/或.Select()来添加其他实体/属性。人们会注意到我上面的最新UPDATED查询在.Select()中添加了一个“新客户”,它曾经是匿名的。我很肯定这就是为什么查询失败b / c它无法变成有效的Uri,因为LatestOrderDate不是服务器级别的Customer属性。仅供参考,在看到下面的第一个答案后,我将该属性添加到我的客户端Customer类中,并使用简单的{get;组; }。所以,鉴于此,我可以以某种方式仍然拥有一个Customer集合,只从两个不同的实体中带回那两个字段吗?下面的解决方案看起来很有前途和巧妙!

    ---- END UPDATE 1 ----

    仅供参考,我使用的技术是OData(WCF),Silverlight,C#。

    任何提示/链接都将受到赞赏。

2 个答案:

答案 0 :(得分:2)

这将为您提供{ OrderId, LatestDate }个对象的列表

var query = Context.Customers
                   .Where(c => c.CustomerId == SelectedCustomer.CustomerId)
                   .SelectMany(c => c.Orders)
                   .Select(o => new { 
                              OrderId = o.OrderId, 
                              LatestDate = o.Statuses.Max(s => s.StatusDate) });

               .

UPDATE 构造内存中的对象

var query = Context.Customers
                   .Where(c => c.CustomerId == SelectedCustomer.CustomerId)
                   .SelectMany(c => c.Orders)
                   .AsEnumerable() // goes in-memory
                   .Select(o => new { 
                              OrderId = o.OrderId, 
                              LatestDate = o.Statuses.Max(s => s.StatusDate) });

此外,分组也可以提供帮助。

答案 1 :(得分:0)

如果我正确读取了这个,你想要一个Customer实体,然后从它的Orders属性计算一个值。目前OData不支持此功能。 OData不支持查询中的计算值。所以投影中没有表达,没有聚合等等。

不幸的是,即使有两个查询,这也是不可能的,因为OData不支持任何表达MAX功能的方式。

如果您可以控制服务,则可以编写服务器端功能/服务操作来执行此类查询。