【问题标题】:Loading the last related record instantly for multiple parent records using Entity framework使用实体框架立即为多个父记录加载最后一条相关记录
【发布时间】:2012-10-17 23:26:11
【问题描述】:

有没有人知道使用实体框架解决下述问题的好方法?

我正在尝试在我们的下一个版本中提供一种高效的方式来显示已登录客户的已下订单。 当然,当有大量数据可用时,分页始终是一种很好的技术。我希望看到没有任何分页技术的答案。

故事如下:客户下了订单,订单状态 = PENDING。根据某些策略,我们将该订单向上移动以使其获得批准。 状态的每一次变化都会被记录下来,这样我们就可以看到状态的跟踪,甚至可以看到每个状态的额外注释行,这可以为在界面中看到此订单的任何人提供一些额外的有价值的信息。

因此,订单与客户相关联。一个订单可以有多个订单状态存储在 OrderStatusHistory 中。

在我的测试场景中,我使用的客户有 100 多个订单,每个订单在 OrderStatusHistory 表中大约有 5 条记录。 我现在想在一个页面中查看所有订单,而不使用分页,在每个订单我显示最后一个相关状态和额外评论(如果有任何最后一个状态;两个字段都来自 OrderStatusHistory;最高记录给定 OrderId 的 ID)。

我尝试过多种方案,但我希望在我已经尝试过的事情上看到任何潜在的其他解决方案或 cmets。

  • 在获取订单时尝试执行 Include(),但这仍会导致在数据库上启动多个查询。每个订单都会触发对数据库的额外查询,以获取历史表中的所有订单状态。因此,这里查询所有状态,而不是只返回最后一个相关的状态,另外还会针对 100 个订单启动 100 个额外查询。当数据库中有超过 100000 个订单时,您可以想象这个问题。
  • 在数据库中有 2 个计算列:LastStatus、LastStatusInformation 和一个常规的 Linq-Query,它获取通过 Entity-model 可用的那些列。 这种方法的问题在于,这些计算列是使用标量函数确定的,如果不从计算列中删除公式等,就无法更改该函数...

最后我非常熟悉 SQL 和存储过程,但是由于数据层的其余部分使用实体框架,我想尽可能坚持下去,即使我对性能有疑问。 使用 SQL 方法我会写这样的东西:

WITH cte (RN, OrderId, [Status], Information)
AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY Id DESC), OrderId,    [Status], Information
FROM OrderStatus
)
SELECT o.Id, cte.[Status], cte.Information AS StatusInformation, o.* FROM [Order] o
INNER JOIN cte ON o.Id = cte.OrderId AND cte.RN = 1
WHERE CustomerId = @CustomerId
ORDER BY 1 DESC;

返回客户的所有订单以及公共表表达式提供的状态信息。

有人知道使用实体框架的好方法吗?

【问题讨论】:

    标签: database linq entity-framework linq-to-sql


    【解决方案1】:

    这样的东西应该可以按你的意愿工作(只调用 1 个数据库),但我没有测试它:

    var result = from order in context.Orders
                 where order.CustomerId == customerId
                 let lastStatus = order.OrderStatusHistory.OrderBy(x => x.Id).Last()
                 select new
                 {
                     //you can return the whole order if you need
                     //Order = order,
                     //or only the information you actually need to display
                     Number = order.Number,
                     Status = lastStatus.Status,
                     ExtraComment = lastStatus.ExtraComment,
                 };
    

    这假设您的 Order 类看起来像这样:

    public class Order
    {
        public int Id { get; set; }
        public int CustomerId { get; set; }
        public string Number { get; set; }
        ...
        public ICollection<OrderStatusHistory> OrderStatusHistory { get; set; }
    }
    

    如果您的 Order 类没有类似 ICollection&lt;OrderStatusHistory&gt; OrderStatusHistory 的属性,那么您需要先进行连接。如果是这种情况,请告诉我,我将编辑我的答案以包含join

    【讨论】:

    • 听起来是个不错的方法。我明天在工作中测试这个。当我分析这个查询时,很好奇它的性能和输出。
    猜你喜欢
    • 2016-09-10
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    • 2020-12-04
    相关资源
    最近更新 更多