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

C# 实体框架-存储过程的执行时间非常长,c#,sql-server,entity-framework,stored-procedures,C#,Sql Server,Entity Framework,Stored Procedures,我昨天正在跟进我的问题。我的存储过程现在在实体框架下运行。但是,它在3分钟后超时,连接超时 我在SQL Server Management Studio中使用以下行运行存储过程(省略客户信息): 它在不到一秒钟的时间内执行。当实体framwork执行它时,它将花费永远的时间 使用SQL Server探查器,我确定Entity Framework正在将此行发送到SQL Server: exec sp_executesql N'EXEC spGetDupWOs',N'@ProjectName nva

我昨天正在跟进我的问题。我的存储过程现在在实体框架下运行。但是,它在3分钟后超时,连接超时

我在SQL Server Management Studio中使用以下行运行存储过程(省略客户信息):

它在不到一秒钟的时间内执行。当实体framwork执行它时,它将花费永远的时间

使用SQL Server探查器,我确定Entity Framework正在将此行发送到SQL Server:

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();
列出重复的检查结果=
SqlQuery(“spGetDupWOs”,
spl.ToArray())
.ToList();

在网上读了一大堆文章后,我更加困惑了。如何更改调用以解决此问题?

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

这里有一些选择

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

  • 优化提示。这可能是参数嗅探的一种解决方法,但可能会导致所有查询的执行计划都低于标准。通常,这不是一种最佳方法。要实现:使用选项(针对未知优化)

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

  • 在查询级别关闭参数嗅探。此方法使用QUERYTRACEON提示。对于这种情况,这可能是最理想的方法。我建议将这一选择作为主要战略加以探讨。要实现:在查询末尾添加选项(QUERYTRACEON 4136)

  • 例如:

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

    最后,我不得不将整个调用转换为一个字符串,并将其传递给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前缀才能使它工作,我不知道为什么,但它工作了


    谢谢大家的帮助。如果没有您的帮助,我无法解决此问题。

    您是否尝试过修复参数嗅探场景?仅此而已。我被我读到的东西弄糊涂了,我不知道怎么读。是否需要更改存储过程或应用程序调用?更改SP。例如:
    CREATE PROC Thing(@param1 INT)为DECLARE@internal_param1 INT=@param1;从Column=@internal_param1
    @DavidG的表中选择*:虽然这可以解决参数嗅探问题,但与单个麻烦语句的
    选项(优化…
    选项(重新编译)
    相比,这是一种不直观的方法。本地复制参数应该是不必要的。@Jeroenmoster我不建议将这两种方法都作为参数嗅探的解决方案。我实现了第3种方法,几乎成功了。通过在SP中添加一些调试信息,我可以确定存储过程没有获得提供给它的参数。我最终将整个调用转换为字符串,并将其传递给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");