2017-03-09 98 views
3

昨天我跟进了我的问题Entity Framework 6 get complext return value from a stored procedure。我的存储过程现在在实体框架下运行。但是,3分钟后超时,连接超时。实体框架 - 存储过程的执行时间非常长

我跑在我的SQL Server Management Studio中存储过程与线(省略客户信息):

EXEC spGetDupWOs @ProjectName=N'...', @City=N'...', @State=N'LA', @ProposalNum=N'201703080740-001', @County=N'...', @Owner=N'...', @QuoteRecipients=N'...', @ProjectID=-1 

它执行在不到一秒钟。当实体框架执行它时,它需要永远。

使用SQL Server事件探查,我决定实体框架正在发送这一行到SQL服务器:

exec sp_executesql N'EXEC spGetDupWOs',N'@ProjectName nvarchar(19),@City nvarchar(6),@State nvarchar(2),@ProjectNum nvarchar(12),@County nvarchar(10),@Owner nvarchar(23),@QuoteRecipients nvarchar(23),@ProjectID bigint',@ProjectName=N'...',@City=N'Holden',@State=N'LA',@ProposalNum=N'201703080740-001',@County=N'Livingston',@Owner=N'...',@BID_RECIP=N'...',@ProjectID=-1 

当我在SSMS运行它,它永远运行。

阅读类似的问题看起来像问题是参数嗅探和执行计划的变化。

这里是我的电话在我的应用程序执行存储过程:

  List<DuplicateProposals> duplicateCheckResults = 
       db.Database.SqlQuery<DuplicateProposals>("spGetDupWOs", 
       spl.ToArray()) 
       .ToList(); 

在线阅读一堆的文章后,我更糊涂了。我如何更改我的电话以解决此问题?

+0

您是否尝试过修复参数嗅探场景? – DavidG

+0

就是这样。我对读到的东西感到困惑,我不知道如何。我是否需要更改存储过程或我的应用程序调用? –

+0

更改SP。例如:CREATE PROC Thing(@ param1 INT)AS DECLARE @ internal_param1 INT = @ param1; SELECT * FROM Table WHERE Column = @ internal_param1' – DavidG

回答

0

我最后不得不整个呼叫转换成我传递给sqlquery函数一个字符串。

  string sql = string.Format("exec spGetDupWOs @ProjectName=N'{0}',@City=N'{1}',@State=N'{2}',@ProjectNumber=N'{3}',@County=N'{4}',@Owner=N'{5}',@QuoteRecipients=N'{6}',@ProjectID={7}", 
       project.ProjectName, 
       project.City, 
       project.State, 
       project.ProjectNumber, 
       project.County, 
       project.Owner, 
       quoteRecipientsList, 
       "null"); 

是的,我必须包括N个前缀字符串,使其工作,我不知道为什么,但它的工作。

感谢所有人的帮助。没有你的帮助,我无法解决这个问题。

1

确定的问题是SQL Server中的参数嗅探。有多种方法可以处理这种情况,但对于您的情况而言,最优化取决于您的实际使用情况,利用率等。

以下是一些选项。

  1. 在每次执行时重新编译存储过程。这可能会导致CPU利用率非常高,并且通常是过度的。除非你有很好的理由,否则我不会推荐这个选项。要实现:使用 WITH RECOMPILEOPTION(RECOMPILE)在查询结束提示。

  2. 优化提示。这可能是参数嗅探的一种解决方法,但可能会导致所有查询的子执行计划。通常,不是最佳方法。执行:使用OPTION(OPTIMIZE FOR UNKNOWN)

  3. 将参数复制到局部变量。在旧版本的SQL Server中更常见。要实现:声明一个局部变量,然后将输入参数中的值复制到本地变量中。 DECLARE @ local_var1 char(1)= @ InputParam1;

  4. 关闭参数的查询级别嗅探。此方法使用QUERYTRACEON提示。这可能是这种情况下最理想的方法。我会建议探索这个选项作为主要策略。执行:在您的查询结尾处添加OPTION(QUERYTRACEON 4136)

例子:

SELECT * FROM dbo.MyTable T 
WHERE T.Col1 = @Param1 and T.Col2 = @Param2 
OPTION(QUERYTRACEON 4136) 
+0

我实现了3号,它几乎工作。我能够通过在SP中添加一些调试信息来确定存储过程没有获得提供给它的参数。我最终将整个调用转换为一个字符串并将其传递给SqlQuery函数。 –