如何捕获 SQLServer 超时异常

Posted

技术标签:

【中文标题】如何捕获 SQLServer 超时异常【英文标题】:How to catch SQLServer timeout exceptions 【发布时间】:2010-09-06 23:28:14 【问题描述】:

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

try

    //some code

catch (SqlException ex)


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

【问题讨论】:

您是在寻找 ConnectionTimeout 还是 CommandTimeout,即您希望连接失败还是执行的命令失败? 我正在寻找一个 CommandTimeout,我认为它默认设置为 30 秒 【参考方案1】:

SqlException.ErrorCode 属性的值是多少?你能用它吗?

当出现超时时,可能值得检查 -2146232060 的代码。

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

【讨论】:

查看错误代码的文档,在我看来,它报告了互操作级别的错误。因此,它可能更多是在 COM 错误级别上,或者提供商遇到了异常(通常),而不是与您正在执行的操作相关的特定错误。 @Eric 是正确的 - 这是 SqlException 类型的 HRESULT 代码,而不是异常源。【参考方案2】:

要检查超时,我相信您检查 ex.Number 的值。如果是-2,那么你有超时情况。

-2 是超时的错误代码,从 SQL Server 的 MDAC 驱动程序 DBNETLIB 返回。这可以通过下载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 并不是很优雅 下载Red Gate的Reflector,搜索TIMEOUT_EXPIRED。它位于 System.Data.SqlClient.TdsEnums 中,其值为 -2。 :o) 对于没有使用Reflector的人:link @brodie 这就是为什么你应该为它创建一个常量,你可以在常量的评论中解释“神奇”值的来源。【参考方案3】:

这里: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 错误代码)

...

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

【讨论】:

【参考方案4】:

为 c# 6 更新:

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

非常简单好看!!

【讨论】:

谢谢...我喜欢你的建议并使用它。【参考方案5】:

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

【讨论】:

【参考方案6】:

当客户端发送 ABORT 时,不会回滚任何事务。为了避免这种行为,我们必须使用 SET_XACT_ABORT ON https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql?view=sql-server-ver15

【讨论】:

它没有回答如何在 c# 代码中捕获命令超时的问题

以上是关于如何捕获 SQLServer 超时异常的主要内容,如果未能解决你的问题,请参考以下文章

如何捕获sqlserver数据库的异常

如何将java程序里的一段连接mysql的语句转为连接sqlserver语句。连接的是sqlser

使用 Guzzle 捕获 CUrl 超时异常

java axis2 调用webservice 怎么捕获超时异常(即超时了让它停下来,不要报错)

SQLServer异常捕获(Try Catch)

求人指点下如何捕获SQL连接异常