如何捕获SQLServer超时异常


117

我需要专门捕获SQL Server超时异常,以便可以对它们进行不同的处理。我知道我可以捕获SqlException,然后检查消息字符串是否包含“ Timeout”,但想知道是否有更好的方法吗?

try
{
    //some code
}
catch (SqlException ex)
{

    if (ex.Message.Contains("Timeout"))
    {
         //handle timeout
    }
    else
    {
         throw;
    }
}

您是否正在寻找ConnectionTimeout或CommandTimeout,即您期望连接失败还是执行的命令失败?
edosoft

我正在寻找CommandTimeout,我认为它设置为默认的30秒
brodie

Answers:


157

要检查超时,我相信您可以检查ex.Number的值。如果为-2,则表示超时。

-2是超时错误代码,它是从DBNETLIB(SQL Server的MDAC驱动程序)返回的。可以通过下载Reflector并在System.Data.SqlClient.TdsEnums下查找TIMEOUT_EXPIRED 来看到。

您的代码将显示为:

if (ex.Number == -2)
{
     //handle timeout
}

演示失败的代码:

try
{
    SqlConnection sql = new SqlConnection(@"Network Library=DBMSSOCN;Data Source=YourServer,1433;Initial Catalog=YourDB;Integrated Security=SSPI;");
    sql.Open();

    SqlCommand cmd = sql.CreateCommand();
    cmd.CommandText = "DECLARE @i int WHILE EXISTS (SELECT 1 from sysobjects) BEGIN SELECT @i = 1 END";
    cmd.ExecuteNonQuery(); // This line will timeout.

    cmd.Dispose();
    sql.Close();
}
catch (SqlException ex)
{
    if (ex.Number == -2) {
        Console.WriteLine ("Timeout occurred");
    }
}

是的,这几乎是我目前正在做的事情,但是检查-2并不是很优雅
brodie

12
下载Red Gate的Reflector,然后搜索TIMEOUT_EXPIRED。它位于System.Data.SqlClient.TdsEnums中,其值为-2。:o)
乔纳森·

2
对于那些无法使用Reflector的用户:链接
ankitk

4
@brodie这就是为什么要为其创建一个常量,并且可以在对该常量的注释中解释“魔术”值来自何处的原因。
Jason L.

18

此处:http : //www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.adonet/2006-10/msg00064.html

您还可以阅读Thomas Weingartner写道:

超时:SqlException.Number == -2(这是ADO.NET错误代码)
常规网络错误:SqlException.Number == 11
死锁:SqlException.Number == 1205(这是SQL Server错误代码)

...

我们也将“常规网络错误”作为超时异常处理。它仅在极少数情况下发生,例如当您的更新/插入/删除查询将引发长时间运行的触发器时。


6

为c#6更新:

    try
    {
        // some code
    }
    catch (SqlException ex) when (ex.Number == -2)  // -2 is a sql timeout
    {
        // handle timeout
    }

很简单,很高兴看!


0

SqlException.ErrorCode属性的值是什么?你可以用吗?

超时时,值得检查-2146232060的代码。

我会在您的数据代码中将其设置为静态const。


2
查看有关ErrorCode的文档,在我看来,它正在报告互操作级错误。因此,它可能更多是在COM错误方面,或者是提供程序遇到了异常(通常),而不是遇到与您正在执行的操作有关的特定错误。
埃里克·塔特尔曼

@Eric是正确的-这是SqlException类型的HRESULT代码,而不是异常源。
codekaizen 2011年

0

我不确定,但是当我们执行超时或命令超时时,客户端会向SQL Server发送“ ABORT”,然后简单地放弃查询处理。没有事务回滚,没有锁释放。解决此问题的方法是删除存储过程中的事务,并在我的.Net代码中使用SQL事务来管理sqlException


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.