0

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

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

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

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

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

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

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

最后我对 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;

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

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

4

1 回答 1

3

像这样的东西应该可以按您的意愿工作(只进行 1 db 调用),但我没有测试它:

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<OrderStatusHistory> OrderStatusHistory属性的东西,那么您需要先加入。让我知道是否是这种情况,我将编辑我的答案以包含join.

于 2012-11-12T16:09:00.710 回答