在c#中编写这个sql查询的合理快速方法是什么?

时间:2013-04-05 19:17:22

标签: sql linq linq-to-entities

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

1 个答案:

答案 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>