Database.ExecuteSqlCommand()在执行存储过程时挂起

时间:2018-07-12 18:03:58

标签: c# sql entity-framework asp.net-web-api

我正在使用一个我没有太多控制权的数据库。我正在尝试在C#Web API调用中使用Database.ExecuteSqlCommand方法执行存储过程。我已经能够成功地在其他存储过程上使用此方法,而没有任何问题。但是,当我尝试执行此特定的存储过程时,应用程序冻结。我将其放在try catch中,并且不会引发任何异常。它将无限期地保持这种状态。我必须进入SSMS并终止与呼叫相关的进程。当我终止该过程时,Web API将继续。如果我在SSMS中执行相同的EXEC命令,则返回单个行RETURN_VALUE = 0即可正常工作。我在过程结束时手动添加了此RETURN_VALUE = 0,以为这可能是问题的一部分。

C#代码为:

try
{
    entities.Database.ExecuteSqlCommand("EXEC [dbo].[SPCHANGEORDER]");
    return Ok();
}
catch (Exception e)
{
    Console.WriteLine(e.ToString());
    return Content(HttpStatusCode.BadRequest, "SQL Server Exception");
}

存储过程确实会调用其他一些存储过程以及某些插入,更新和删除操作。我知道其中一个嵌套存储过程也会执行几个EXEC xp_cmdshell命令。我知道这还不算什么,但是我希望有人可以帮助我至少找到错误的路径。谢谢!

编辑 我使用了SQL Server Profiler,并找到了它的执行位置。我将集合复制/粘贴到SSMS查询窗口中,但仍然能够成功执行存储的过程。

探查器窗口

Profiler Window

SSMS查询

SSMS Query

1 个答案:

答案 0 :(得分:0)

默认情况下,EF将本机SQL Command调用包装在事务中。取决于您的存储过程做什么,这可能是问题所在。例如,如果您的存储过程进行了链接服务器调用,则可能导致它需要分布式事务。

我怀疑这里正在发生的事情是事务导致了不可检测的死锁,因为您的过程正在调用xp_cmdshell。如果该外部程序试图读取您的存储过程写入的数据,则将其包装在事务中将导致该外部程序看不到您的更改,或者阻止您未提交的事务。 (由于您存储的proc使用xp_cmdshell间接创建第二个连接,因此SQL Server无法检测到死锁。)

任何禁用交易的尝试:

entities.Configuration.EnsureTransactionsForFunctionsAndCommands = false;
entities.Database.ExecuteSqlCommand("EXEC [dbo].[SPCHANGEORDER]");