实体框架 - 存储过程的执行时间非常长

时间:2017-03-09 16:35:46

标签: c# sql-server entity-framework stored-procedures

我昨天正在跟进我的问题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 Profiler,我确定实体框架正在将此行发送到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();

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

2 个答案:

答案 0 :(得分:0)

确定的问题是SQL Server中的参数嗅探。有多种方法可以解决这个问题,但最适合您的方案取决于您的实际用例,利用率等。

以下是一些选项。

  1. 每次执行时重新编译存储过程。这可能会变得非常繁重的CPU利用率,并且通常是过度的。除非你有充分的理由,否则我不推荐这个选项。实施:使用 在您的查询结尾处 WITH RECOMPILE OPTION(RECOMPILE)提示。

  2. 优化提示。这可以是参数嗅探的变通方法,但可能会导致所有查询的subpar执行计划。通常,不是最佳方法。实施:使用选项(未知优化)

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

  4. 在查询级别关闭参数嗅探。此方法使用 QUERYTRACEON 提示。对于这种情况,这可能是最佳方法。我建议将此选项作为主要策略进行探索。要实现:在查询末尾添加 OPTION(QUERYTRACEON 4136)

  5. 示例:

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

答案 1 :(得分: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前缀才能使其正常工作,我不知道为什么会这样做但是有效。

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