【问题标题】:LINQ Query - Only get Order and MAX Date from Child CollectionLINQ 查询 - 仅从子集合中获取订单和最大日期
【发布时间】:2012-10-27 09:23:05
【问题描述】:

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

我有 3 个实体:

  1. [客户]:客户 ID、姓名、地址……
  2. [Order]:OrderId, OrderDate, EmployeeId, Total, ...
  3. [OrderStatus]:OrderStatusId、StatusLevel、StatusDate,...

一个客户可以有很多订单,而一个订单又可以有很多OrderStatus,即 [客户] 1--* [订单] 1--* [订单状态]

给定一个 CustomerId,我想获取该订单的所有订单(仅 OrderId)和最新的(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 的项目的集合,因为我必须通过一个严格的 API 中的约束,该 API 有一个 IQueryable 查询作为其参数之一。我知道我可以使用扩展方法 .Expand() 和/或 .Select() 添加其他实体/属性。人们会注意到我上面最新的 UPDATED 查询在 .Select() 中添加了一个“新客户”,它曾经是匿名的。我很肯定这就是为什么查询失败的原因 b/c 由于 LatestOrderDate 不是客户在服务器级别的属性,它不能变成有效的 Uri。仅供参考,在看到下面的第一个答案后,我使用简单的 { get; 将该属性添加到我的客户端 Customer 类中。放; }。因此,鉴于此,我能否以某种方式仍然拥有一个 Customer 集合,只从 2 个不同的实体中带回这 2 个字段?下面的解决方案看起来如此有前途和巧妙!

---- 结束更新 1 ----

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

任何提示/链接将不胜感激。

【问题讨论】:

    标签: c# linq entity-framework


    【解决方案1】:

    这将为您提供{ 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) });
    
                   .
    

    更新在内存中构造对象

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

    在这里分组也有帮助。

    【讨论】:

    • 感谢您的回复,不过我刚试了一下,收到如下:
    • 下面的不是你想要的吗?
    • 对不起!我必须在复制错误然后将其删除时删除了错误。这就是我得到的: ------------------------------------------ 'iexplore .exe'(Silverlight):加载“匿名托管的 DynamicMethods 程序集”将 Linq 表达式转换为 URI 时出错:使用表达式 o.OrderStatus.Max(s => s.StatusDate) 初始化实体类型 xxx.Service.Customer 的实例不是支持的。 ------------------------------------------------------
    • @user118190 对不起,现在没有太多时间,用最简单的解决方案更新。一小时后回来
    • 感谢您的帮助,非常感谢。我查看了您的代码和您正在使用的一些概念并学到了更多。由于我最初的查询/要求不太正确,因此我已经更新了我的原始帖子并提供了更多详细信息。
    【解决方案2】:

    如果我没看错的话,您需要一个 Customer 实体,然后是从其 Orders 属性计算的单个值。目前 OData 不支持此功能。 OData 不支持查询中的计算值。所以投影中没有表达式,没有聚合等等。

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

    如果你可以控制服务,你可以编写一个服务器端函数/服务操作来执行这种查询。

    【讨论】:

      猜你喜欢
      • 2015-12-12
      • 2015-12-08
      • 2021-06-26
      • 2018-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      相关资源
      最近更新 更多