3

我有这个 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. 结果被清楚地缓存了,因为它返回具有不同参数的完全相同的值。

4

1 回答 1

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)

于 2013-04-05T19:29:00.590 回答