c# - 提高 LINQ 枚举器内条件查询的性能

标签 c# performance linq linq-to-sql

我有一些看起来像这样的代码,使用 .NET 3.5(客户要求):

void Process (ActionState state)
{
    var orderItemQuery = from OrderItem item in order.OrderItems
                           orderby item.OrderLineNumber ascending
                           select item;

    foreach (OrderItem item in orderItemQuery)
    {
        ActionData actionData;
        switch (state)
        {
            case ActionState.Prepare:
                actionData = (
                    from ActionData ad in db.ActionDataTable
                      where ad.ObjectId == item.ProductId
                      select ad
                ).First();

            case ActionState.QualityCheck:
                actionData = (
                    from ActionData ad in db.ActionDataTable
                      where ad.ObjectId == item.OrderItemId
                      select ad
                ).First();

            default:
                throw new InvalidOperationException();
        }

        // ...
    }
}

本质上,第一个查询的结果是迭代的,并且根据当前的 ActionState,使用特定的外键从数据库中获取 ActionData 记录。实际上,这里那里有更多的嵌套和一些检查,但本质上是相同的。

这最初对于测试数据库来说效果很好,但是客户刚刚向我发送了他们的实时数据的副本,而且速度慢得可怕。运行整个批处理大约需要 15 分钟,包括一些其他处理。通过性能测试器运行代码后,我发现整个过程中最慢的部分是每种情况下的 .First() 调用。

如果这是普通的 SQL,我将根据 state 的值在循环外部编译一个存储过程,并使用它。既然我不能这样做,那么还有什么选择呢?我怎样才能加快速度?

最佳答案

您的问题是您的代码对数据库执行了 100500 个请求。您需要通过一次请求获得您想要的东西。为此,您需要编写正确的 linq 查询。像这样的东西:

if(state!=ActionState.Prepare&&state!=ActionState.QualityCheck)
    throw new InvalidOperationException();
var orderSelector = state == ActionState.Prepare
                             ?o=>o.ProductId
                             :?o=>o.OrderItemId
var orderWithActionQuery  = order.OrderItems.Orderby(o => o.OrderLineNumber).GroupJoin(
        db.ActionDataTable,
        orderSelector,
        ad => ad.ObjectId,
        (x, y) => new { item = x, actionDatas = y })
        .Select(c => new {item = c.item, actionData = c.actionDatas.FirstOrDefault()});    
foreach(var orderWithActionData in orderWithActionQuery)
{
     //orderWithActionData.item is orderItem
     //orderWithActionData.actionData is ation data of this item
}

在此代码中,对数据库的请求将按照 foreach 发送。这将是单个请求,性能会很好

关于c# - 提高 LINQ 枚举器内条件查询的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12802221/

相关文章:

c# - EF - 如果使用实体对象,则重新插入外键

javascript - 这个的时间复杂度是多少以及如何使其为 0(n)?

javascript - 无卡顿体验和 websocket

c# - 合并列表并只返回重复项

c# - LINQ to Nhibernate 用户在 where 子句中定义的函数

c# - LINQ 性能计数 vs Where 和 Count

c# - .exe 和 .dll 之间的共享配置

c# - Webdeploy权限问题

performance - 可以使用SIMD或其他方法加快Delphi 6位图修改代码的速度吗?

c# - Gridview Binding DropDownList 来自后面的代码