我有两个集合,有些条件是使用linq查询完成的。比较两个列表并从中获取结果。我使用了foreach循环和linq查询,这些集合有65000个数据,我的问题是它需要更多的时间来处理。我的代码如下所述。如何提高性能以及如何缩短处理时间。如果有任何提高性能的想法请分享。
foreach (var part in quoteParts)
{
var presentPart = existingPart.FirstOrDefault(p => p.PartName == part.PartNumber);
if (presentPart != null)
{
int partID = presentPart.ID;
string partNumber = Convert.ToString(presentPart.PartName);
foreach (var quotesPart in quoteStepInProcesses)
{
var presentStepInProcess = existingStepInProcesses.FirstOrDefault(p => p.ProcessId == quotesPart.StepInProcessID && quotesPart.PartNumber == partNumber);
if (presentStepInProcess != null)
{
PartProcesses.Add(new PartProcessDto
{
ProcessName = Convert.ToString(presentStepInProcess.ID),
PartName = Convert.ToString(presentPart.ID)
});
}
}
}
}
答案 0 :(得分:9)
您至少有两个地方在循环中使用FirstOrDefault
来查找记录。我要尝试的第一件事就是预先索引数据;例如:
var partsByName = existingPart.ToDictionary(x => x.PartName);
foreach (var part in quoteParts)
{
if(partsByName.TryGetValue(part.PartNumber, out var presentPart))
{
// ...
}
}
与existingStepInProcesses
通过ProcessId
类似。另请注意,最里面的FirstOrDefault
(&& quotesPart.PartNumber == partNumber
)中的第二次测试实际上并未过滤p
,因此应该从该查找移动远离。所以:在第一个ToDictionary
旁边的第一个循环之外:
var processes = existingStepInProcesses.ToDictionary(x => x.ProcessId);
然后在最里面的循环中:
if (quotesPart.PartNumber == partNumber &&
processes.TryGetValue(quotesPart.StepInProcessID, out var presentStepInProcess))
{
// ...
}
您可能也可以使用quoteStepInProcesses
删除第二个foreach
- 这取决于您期望的匹配数量。如果有多个:可能.ToLookup
而不是ToDictionary
。