我有这个SQL查询:
select
sum(h.nbHeures)
from
Heures h
join
HeuresProjets hp on h.HpGuid=hp.HPId
join
ActivityCodes ac on h.Code=ac.ActivityId
join
MainDoeuvre mdo on ac.ActivityId=mdo.CodeGuid
where
hp.ExtraGuid = '61E931C8-3268-4C9C-9FF5-ED0213D348D0'
and mdo.NoType = 1
它在不到一秒的时间内运行,这很好。我的项目使用LINQ to实体来获取数据。这(非常类似于sql)查询非常慢,耗时超过一分钟。
var result = (from hp in this.HeuresProjets
join h in ctx.Heures on hp.HPId equals h.HpGuid
join ac in ctx.ActivityCodes on h.Code equals ac.ActivityId
join mdo in ctx.MainDoeuvre on ac.ActivityId equals mdo.CodeGuid
where hp.ExtraGuid == this.EntityGuid && mdo.NoType == (int)spType
select h.NbHeures).Sum();
total = result;
我尝试使用嵌套循环。它速度更快但仍然很慢(约15秒)。
foreach (HeuresProjets item in this.HeuresProjets)
{
foreach (Heures h in ctx.Heures.Where(x => x.HpGuid == item.HPId))
{
if (h.ActivityCodes != null && h.ActivityCodes.MainDoeuvre.FirstOrDefault() != null && h.ActivityCodes.MainDoeuvre.First().NoType == (int)type)
{
total += h.NbHeures;
}
}
}
我做错了什么吗?如果没有办法优化这个,我只会调用一个存储过程,但我真的希望保留代码中的逻辑。
修改
我根据IronMan84的建议修改了我的查询。
decimal total = 0;
var result = (from hp in ctx.HeuresProjets
join h in ctx.Heures on hp.HPId equals h.HpGuid
join ac in ctx.ActivityCodes on h.Code equals ac.ActivityId
join mdo in ctx.MainDoeuvre on ac.ActivityId equals mdo.CodeGuid
where hp.ExtraGuid == this.EntityGuid && mdo.NoType == (int)spType
select h);
if(result.Any())
total = result.Sum(x=>x.NbHeures);
这几乎可行。它快速运行并返回小数但是:
1.它不是正确的价值
2.结果显然是缓存的,因为它返回具有不同参数的完全相同的值。
答案 0 :(得分:3)
通过查看您的代码,我认为您的查询正在抓取您加入的那些表中的每条记录(因此需要很长时间)。我看到你使用this.HeuresProjets
,我假设它是你已经从数据库中抓取的数据库对象的集合(这就是你没有使用ctx.HeuresProjets
的原因)。那么,当你进入连接查询时,那个集合可能已经被水合了。在这种情况下,它成为LINQ-To-Objects查询,因此需要EF去抓取所有其他表的记录才能完成连接。
假设我的假设是正确的(如果我错了就让我知道),你可能想尝试一下:
var result = (from hp in ctx.HeuresProjets
join h in ctx.Heures on hp.HPId equals h.HpGuid
join ac in ctx.ActivityCodes on h.Code equals ac.ActivityId
join mdo in ctx.MainDoeuvre on ac.ActivityId equals mdo.CodeGuid
where hp.ExtraGuid == this.EntityGuid && mdo.NoType == (int)spType
select h).Sum(h => h.NbHeures);
total = result;
此外,如果this.HeuresProjets
是仅包含特定对象的筛选列表,则只需添加到查询的where
子句即可确保ID位于this.HeuresProjets.Select(hp => hp.HPId)
< / p>