Как поймать исключения тайм-аута SQLServer


117

Мне нужно специально перехватывать исключения тайм-аута SQL-сервера, чтобы их можно было обрабатывать по-другому. Я знаю, что могу поймать SqlException, а затем проверить, содержит ли строка сообщения «Тайм-аут», но мне было интересно, есть ли лучший способ сделать это?

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

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

Вы ищете ConnectionTimeout или CommandTimeout, т.е. ожидаете ли вы сбоя соединения или сбоя выполненной команды?
edosoft

Я ищу CommandTimeout, для которого установлено значение по умолчанию 30 секунд, я думаю,
Броди

Ответы:


157

Чтобы проверить тайм-аут, я думаю, вы проверяете значение ex.Number. Если это -2, то у вас ситуация тайм-аута.

-2 - это код ошибки для тайм-аута, возвращаемый DBNETLIB, драйвером MDAC для SQL Server. Это можно увидеть, загрузив 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
Броди

12
Загрузите Reflector Red Gate и найдите TIMEOUT_EXPIRED. Он находится в System.Data.SqlClient.TdsEnums и имеет значение -2. : o)
Джонатан

2
Для тех, у кого нет доступа к Reflector: ссылка
ankitk

4
@brodie Вот почему вы должны сделать для него константу, и вы можете объяснить, откуда взялось «магическое» значение, в комментарии к константе.
Джейсон Л.

18

здесь: http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.adonet/2006-10/msg00064.html

Вы также можете прочитать, что Томас Вайнгартнер написал:

Тайм-аут: 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 .

Я бы установил это как статическую константу в вашем коде данных.


2
Глядя на документы для ErrorCode, мне кажется, что он сообщает об ошибках уровня взаимодействия. Таким образом, это может быть больше на уровне ошибок COM или того, что провайдер обнаружил исключение (как правило), а не конкретную ошибку, связанную с тем, что вы делаете.
Эрик Таттлман

@Eric верен - это код HRESULT для типа SqlException, а не для источника исключения.
codekaizen

0

Я не уверен, но когда у нас истекает время ожидания выполнения или время ожидания команды. Клиент отправляет «ABORT» на SQL Server, а затем просто прекращает обработку запроса. Ни одна транзакция не откатывается, блокировки не снимаются. чтобы решить эту проблему, я удаляю транзакцию в хранимой процедуре и использую транзакцию SQL в моем .Net-коде для управления sqlException


-2

Когда клиент отправляет ABORT, транзакции не откатываются. Чтобы избежать такого поведения, мы должны использовать SET_XACT_ABORT НА https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql?view=sql-server-ver15


1
Он не отвечает на вопрос, как поймать тайм-аут команды в коде C #
Джонатан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.