编辑01 :我似乎发现a solution (click for the answer)对我有用。通过预先计算然后应用.Except()
extension method,从一小时到几小时;但是,如果其他人遇到此问题,请保持开放或,如果其他人发现更好的解决方案。
原始问题
我有以下一组查询,用于从源系统暂存的不同种类的对象,因此我可以保持同步并自己制作delta标记,因为源系统不能提供它,我们也不能建立或触摸它。
我获取内存中的所有数据然后例如执行此查询,在那里我查找在源系统中不再存在但在登台数据库中存在的对象 - 因此必须标记"删除&#34 ;.瓶颈是LINQ查询的第一部分 - 在.Contains()
上,如何通过.Except()
与自定义比较器一起改善它的性能?
或者我应该最好将它们放在散列列表中并执行比较?
问题是虽然我之后必须让阶段对象对它们进行一些属性转换,这似乎是最简单的解决方案,但不幸的是它在20k对象上非常慢
stagedSystemObjects.Where(stagedSystemObject =>
!sourceSystemObjects.Select(sourceSystemObject => sourceSystemObject.Code)
.Contains(stagedSystemObject.Code)
)
.Select(x =>
{
x.ActiveStatus = ActiveStatuses.Disabled;
x.ChangeReason = ChangeReasons.Edited;
return x;
})
.ToList();
答案 0 :(得分:1)
我已经找到了解决这个问题的方法 - 这使得它只需要几秒钟而不是一小时的200k物体。
由预先计算完成,然后应用.Except()
extension method
所以不再"链接" linq查询,或在方法中执行.Contains
...但使其更简单"首先将两者都投影到string
列表中,这样内部计算就不必在原始问题的示例代码中反复出现。
这是我的解决方案,目前令人满意。但是,如果有人想出一个精致/更好的解决方案,我就会离开这个!
var stagedSystemCodes = stagedSystemObjects.Select(x => x.Code).ToList();
var sourceSystemCodes = sourceSystemObjects.Select(x => x.Code).ToList();
var codesThatNoLongerExistInSourceSystem = stagedSystemCodes.Except(sourceSystemCodes).ToList();
return stagedSystemObjects
.Where(stagedSystemObject =>
codesThatNoLongerExistInSourceSystem.Contains(stagedSystemObject.Code))
.Select(x =>
{
x.ActiveStatus = ActiveStatuses.Disabled;
x.ChangeReason = ChangeReasons.Edited;
return x;
})
.ToList();
答案 1 :(得分:1)
基于Yves Schelpe的回答。我做了一些调整以使其更快。
基本想法是取消前两个ToList
并使用PLINQ
。看看这个帮助
var stagedSystemCodes = stagedSystemObjects.Select(x => x.Code);
var sourceSystemCodes = sourceSystemObjects.Select(x => x.Code);
var codesThatNoLongerExistInSourceSystem = stagedSystemCodes.Except(sourceSystemCodes).ToArray();
var y = stagedSystemObjects.AsParallel()
.Where(stagedSystemObject =>
codesThatNoLongerExistInSourceSystem.Contains(stagedSystemObject.Code))
.Select(x =>
{
x.ActiveStatus = ActiveStatuses.Disabled;
x.ChangeReason = ChangeReasons.Edited;
return x;
}).ToArray();
请注意,PLINQ可能只适用于具有多核CPU的计算限制任务。在其他情况下,它可能会使事情变得更糟。