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

标签 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 entities 来获取数据。这个(与 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.结果显然被缓存了,因为它返回完全相同的值,但参数不同。

最佳答案

通过查看您的代码,我认为您的查询正在从您要加入的那些表中获取每条记录(因此需要很长时间)。我看到你在使用 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)

关于sql - 在 c# 中编写此 sql 查询的合理快速方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15841790/

相关文章:

c# - Entity Framework 不包括选择语句中的列

sql - 有没有更好的方法来查找表中的条件最后值?

c# - 序列不包含任何元素服务器端

c# - 如何选择与对象列表中的属性值共享属性值的所有对象?

c# - 从dB C#返回相关数据

sql-server - 如何解决与 Entity Framework 的排序规则冲突?

c# - 在与 linq-to-entities 的一对多连接中仅获取一条(最后一条)记录

MySQL查询删除两个已知字符串之间的所有随机数据

mysql - SQL - 如何计算一年中每个月某些服务(具有不同定价)的交易总和?

c# - Entity Framework 4 抽象模型 - 如何以编程方式预加载导航属性?