[英]c# Linq to Objects - FirstOrDefault performance
我们正在尝试优化我们的一些方法。 我们使用Redgate的Performance Profiler来查找一些性能泄漏。
我们的工具在几种方法中使用Linq来对象。 但是我们注意到FirstOrDefault
需要很长时间才能使用+/- 1000个对象。
探查器还会警告查询非常慢。 我已经使用探查器结果添加了图像。
无法将集合添加到数据库,然后查询数据库。 有什么建议?
谢谢 !
private SaldoPrivatiefKlantVerdeelsleutel GetParentSaldoPrivatiefKlantVerdeelsleutel(SaldoPrivatiefKlantVerdeelsleutel saldoPrivatiefKlantVerdeelsleutel, SaldoGebouwRekeningBoeking boeking, int privatiefKlant)
{
SaldoPrivatiefKlantVerdeelsleutel parentSaldoPrivatiefKlantVerdeelsleutel = null;
if (saldoPrivatiefKlantVerdeelsleutel != null)
{
try
{
parentSaldoPrivatiefKlantVerdeelsleutel = saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode.SaldoPrivatiefKlantVerdeelsleutelCollection
.FirstOrDefault(s => (boeking == null || (s.SaldoVerdeelsleutel != null &&
(s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID)))
&& s.PrivatiefKlant.ID == privatiefKlant);
}
catch (Exception ex)
{ }
}
return parentSaldoPrivatiefKlantVerdeelsleutel;
}
图像: 个人资料报告
你应该能够通过重写它来加快速度
saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode.SaldoPrivatiefKlantVerdeelsleutelCollection
.Where(s => (boeking == null || (s.SaldoVerdeelsleutel != null &&
(s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID))) && s.PrivatiefKlant.ID == privatiefKlant)
.FirstOrDefault()
请参阅为什么LINQ .Where(谓词).First()比.First(谓词)快? 为什么这更快。
FirstOrDefault
对源集合执行标准线性搜索,并返回与谓词匹配的第一个元素。 这是O(n) ,因此在更大的收藏品上花费更多时间并不奇怪。
您可以尝试跟随,但增益不会很大,因为它仍然是O(n) 。
private SaldoPrivatiefKlantVerdeelsleutel GetParentSaldoPrivatiefKlantVerdeelsleutel(SaldoPrivatiefKlantVerdeelsleutel saldoPrivatiefKlantVerdeelsleutel, SaldoGebouwRekeningBoeking boeking, int privatiefKlant)
{
SaldoPrivatiefKlantVerdeelsleutel parentSaldoPrivatiefKlantVerdeelsleutel = null;
if (saldoPrivatiefKlantVerdeelsleutel != null)
{
try
{
var query = saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode
.SaldoPrivatiefKlantVerdeelsleutelCollection
.Where(s => s.PrivatiefKlant.ID == privatiefKlant);
if(boeking != null)
{
var gebouwVerdeelSleutelId = boeking.SaldoGebouwRekeningVerdeling
.SaldoGebouwRekening
.SaldoVerdeelsleutel
.GebouwVerdeelSleutel
.ID;
query = query.Where(s => s.SaldoVerdeelsleutel != null &&
s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == gebouwVerdeelSleutelId);
}
parentSaldoPrivatiefKlantVerdeelsleutel = query.FirstOrDefault();
}
catch (Exception ex)
{ }
}
return parentSaldoPrivatiefKlantVerdeelsleutel;
}
它会变得更好,因为boeking != null
check只会执行一次,而不是每个源集合元素。 并且因为嵌套的Where
调用被合并,所以不会导致性能损失。
我会说这个
boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID
可能是罪魁祸首。 尝试在外面缓存它,例如:
var id = boeking != null ? boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID : 0;
并在查询中使用id
。
(我正在做一个假设:那条长链的一个属性做了“不太聪明”的事情,实际上很慢)
您可以尝试将其编写为简单的代码。 LINQ正在使用代理这就是为什么有一点性能受到打击。
try
{
parentSaldoPrivatiefKlantVerdeelsleutel = null;
foreach (var s in saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode.SaldoPrivatiefKlantVerdeelsleutelCollection)
{
if ((boeking == null || (s.SaldoVerdeelsleutel != null && (s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID))) && s.PrivatiefKlant.ID == privatiefKlant)
{
parentSaldoPrivatiefKlantVerdeelsleutel = s;
break;
}
}
}
catch (Exception ex)
{ }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.