C# 在EF6中执行StoredProcedure需要花费大量的时间

C# 在EF6中执行StoredProcedure需要花费大量的时间,c#,sql-server,performance,entity-framework-6,C#,Sql Server,Performance,Entity Framework 6,我正在ASP.NET MVC5中运行EF6(v6.2.0) 当通过EF6的SqlQuery()函数执行某个StoredProcess时,我必须等待大约2分钟(!)才能在内存中获得结果 由于一些复杂的计算,StoredProcedure在数据库中大约需要9-12秒,并使用11个参数调用: exec sp_Calculation @q, @y, @gn, @gesa, @rg, @cl, @yc, @vlv, @vlb, @ugv, @ugb 结果是大约2.1MB的数据(~9000行,49列) 总

我正在ASP.NET MVC5中运行EF6(v6.2.0)

当通过EF6的SqlQuery()函数执行某个StoredProcess时,我必须等待大约2分钟(!)才能在内存中获得结果

由于一些复杂的计算,StoredProcedure在数据库中大约需要9-12秒,并使用11个参数调用:

exec sp_Calculation @q, @y, @gn, @gesa, @rg, @cl, @yc, @vlv, @vlb, @ugv, @ugb
结果是大约2.1MB的数据(~9000行,49列)

总执行时间:
00:00:11.711

在代码中,我这样称呼它:

dbContext.Database.Log = s => Trace.Write(s);
return await dbContext.Database.SqlQuery<CalculationResult>("exec sp_Calculation @q, @y, @gn, @gesa, @rg, @cl, @yc, @vlv, @vlb, @ugv, @ugb", parameters).ToListAsync(token);
我的第一个猜测是网络是一个瓶颈,但是通过SSMS在Web服务器上调用StoredProc也非常快。所以网络不应该是问题所在

下面是dotTrace的调用堆栈,其中有一个大瓶颈: 奇怪的是本机程序集的执行时间非常长

有人能澄清到底发生了什么以及如何解决这个问题吗

编辑: 我刚刚发现了一个类似的问题,并将尝试了解更多有关它的信息。也许它是网络

编辑2:
我确实需要内存中的所有数据,因为在创建csv文件之前需要进行一些预处理。瓶颈似乎在
snNativeMethodWrapper
中。我不需要帮助来执行与其他库的任务。我只是想在内存中更快地获取数据。

我也遇到了同样的问题,当然SSMS的执行速度会更快

问题是,所有记录都被分配给相应的POCO及其属性,它遍历每个值,直到生成一个庞大的对象集

我如何解决这个问题:

我在存储过程中创建了分页(sql级别分页)。 除非你是一个电子人,否则没有人可以一次查看9000多条记录。 因此,在执行存储过程时,只需从结果集中获取10-100条记录

更新:

如果需要检索创建excel的结果集,我建议可能的方法:

  • 直接从创建excel文件,获取结果集 从db到C#非常耗时
  • 如果您在服务器端仍然需要它 那么我建议您使用或任何其他保养良好的产品 在服务器端为您生成excel的第三方库(我使用的是EPPlus) 除SP执行外,我所用的时间不超过5秒 时间)
  • 由于EF和ado之间的差异,切换回ado.net生成报告是可行的
  • 优化您的查询,优化它
  • 如果您的手仍被客户捆住,请忍受当前的加载时间;)
      我也遇到了同样的问题,当然SSM的执行速度会更快

      问题是,所有记录都被分配给相应的POCO及其属性,它遍历每个值,直到生成一个庞大的对象集

      我如何解决这个问题:

      我在存储过程中创建了分页(sql级别分页)。 除非你是一个电子人,否则没有人可以一次查看9000多条记录。 因此,在执行存储过程时,只需从结果集中获取10-100条记录

      更新:

      如果需要检索创建excel的结果集,我建议可能的方法:

      • 直接从创建excel文件,获取结果集 从db到C#非常耗时
      • 如果您在服务器端仍然需要它 那么我建议您使用或任何其他保养良好的产品 在服务器端为您生成excel的第三方库(我使用的是EPPlus) 除SP执行外,我所用的时间不超过5秒 时间)
      • 由于EF和ado之间的差异,切换回ado.net生成报告是可行的
      • 优化您的查询,优化它
      • 如果您的手仍被客户捆住,请忍受当前的加载时间;)
      问题在于数据库和链接服务器之间的负载过重。 本机API很难通过SQL网络接口推送整个记录集。所以代码本身没有问题


      当链接服务器之间的负载较低时,一切都会按预期的速度运行。

      问题是数据库和链接服务器之间的负载较重。 本机API很难通过SQL网络接口推送整个记录集。所以代码本身没有问题


      当链接服务器之间的负载较低时,一切都会按预期的速度运行。

      ORM不用于报告查询。等待9K行返回,将它们转换为列表,然后使用它们也很慢,可能会导致大量的重新分配。使用IEnumerable开始处理结果。毕竟,对于报告或导出,您不需要所有数据,您可以在第一行到达后立即开始写入结果。您还可以使用像Dapper这样的microORM。因为您不需要处理实体,所以不需要更改跟踪、更新支持和完整ORM提供的所有其他功能。只要将DbDataReader行映射到CalculationResult对象,我们就可以在整个应用程序中使用EF6,并使用它的几乎所有功能。所以现在换掉不是一个选择。问题是,加载数据后会有更多的处理。但光是装载就要花那么长时间。在显示跟踪时间时,EF6是否考虑了对象分配?这不是使用错误功能的理由。所以也使用EF。衣冠楚楚。我认为ADO.NET也是必要的。ORM仍然不适合报告导出查询。简单的ADO.NET给了我相同的结果,因此EF6本身没有问题。有些本地的东西看起来很疯狂,但我需要知道到底哪里出了问题。ORMs不适合报告查询。等待9K行返回,将它们转换为列表
      exec sp_Calculation @q, @y, @gn, @gesa, @rg, @cl, @yc, @vlv, @vlb, @ugv, @ugb
      
      -- @q: 'null' (Type = Int32, IsNullable = false)
      -- @y: '1101' (Type = Int16, IsNullable = false)
      -- @gn: 'null' (Type = Int32, IsNullable = false)
      -- @gesa: '1' (Type = Byte, IsNullable = false)
      -- @rg: 'null' (Type = Int32, IsNullable = false)
      -- @cl: '4' (Type = Byte, IsNullable = false)
      -- @yc: '17' (Type = Int16, IsNullable = false)
      -- @vlv: 'null' (Type = Int16, IsNullable = false)
      -- @vlb: 'null' (Type = Int16, IsNullable = false)
      -- @ugv: 'null' (Type = Int16, IsNullable = false)
      -- @ugb: 'null' (Type = Int16, IsNullable = false)
      -- Executing asynchronously at 19.07.2018 18:27:23 +02:00
      -- Completed in 114479 ms with result: SqlDataReader