我有一些看起来像这样的代码,使用 .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/