Jak przechwytywać wyjątki limitu czasu SQLServer

117

Muszę konkretnie złapać wyjątki limitu czasu serwera SQL, aby można było je obsługiwać inaczej. Wiem, że mogę przechwycić wyjątek SqlException, a następnie sprawdzić, czy ciąg wiadomości zawiera „Timeout”, ale zastanawiałem się, czy istnieje lepszy sposób na zrobienie tego?

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

    if (ex.Message.Contains("Timeout"))
    {
         //handle timeout
    }
    else
    {
         throw;
    }
}
brodie
źródło
Czy szukasz ConnectionTimeout lub CommandTimeout, tj. Czy spodziewasz się niepowodzenia połączenia lub wykonania polecenia?
edosoft
Szukam CommandTimeout, który jest ustawiony na domyślny 30 sekund, jak myślę
brodie

Odpowiedzi:

157

Uważam, że aby sprawdzić limit czasu, sprawdź wartość np. Numer. Jeśli jest -2, oznacza to przekroczenie limitu czasu.

-2 to kod błędu przekroczenia limitu czasu, zwrócony z DBNETLIB, sterownika MDAC dla SQL Server. Można to zobaczyć, pobierając Reflector i sprawdzając System.Data.SqlClient.TdsEnums dla TIMEOUT_EXPIRED.

Twój kod brzmiałby:

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

Kod do wykazania awarii:

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");
    }
}
Jonathan
źródło
Tak, to prawie to, co teraz robię, ale nie jest to zbyt eleganckie sprawdzanie -2
brodie
12
Pobierz Red Gate's Reflector i wyszukaj TIMEOUT_EXPIRED. Znajduje się w System.Data.SqlClient.TdsEnums, a jego wartość to -2. : o)
Jonathan
2
Dla tych, którzy nie mają dostępu do Reflectora: link
ankitk
4
@brodie Dlatego powinieneś utworzyć dla niej stałą i możesz wyjaśnić, skąd wzięła się wartość „magiczna” w komentarzu do stałej.
Jason L.
18

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

Możesz również przeczytać, że Thomas Weingartner napisał:

Limit czasu: SqlException.Number == -2 (to jest kod błędu ADO.NET)
Ogólny błąd sieci: SqlException.Number == 11
Zakleszczenie: SqlException.Number == 1205 (to jest kod błędu programu SQL Server)

...

Jako wyjątek dotyczący limitu czasu traktujemy również „Ogólny błąd sieci”. Występuje tylko w rzadkich przypadkach, np. Gdy zapytanie o aktualizację / wstawienie / usunięcie wywoła długo działający wyzwalacz.

Roland Pihlakas
źródło
6

Zaktualizowano dla C # 6:

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

Bardzo proste i przyjemne dla oka !!

John Evans
źródło
0

Jaka jest wartość właściwości SqlException.ErrorCode? Czy możesz z tym pracować?

W przypadku przekroczenia limitu czasu warto sprawdzić kod -2146232060 .

Ustawiłbym to jako statyczną stałą w kodzie danych.

Rob Cooper
źródło
2
Patrząc na dokumentację dla ErrorCode, wydaje mi się, że zgłasza błędy na poziomie międzyoperacyjnym. Więc może być bardziej na poziomie błędów COM lub że dostawca napotkał wyjątek (ogólnie) zamiast konkretnego błędu związanego z tym, co robisz.
Eric Tuttleman
@Eric jest poprawne - to jest kod HRESULT dla typu SqlException, a nie dla źródła wyjątku.
codekaizen
0

Nie jestem pewien, ale kiedy upłynął limit czasu na wykonanie lub przekroczenie limitu czasu polecenia Klient wysyła „ABORT” do SQL Server, a następnie po prostu rezygnuje z przetwarzania zapytania. Żadna transakcja nie jest wycofywana, żadne blokady nie są zwalniane. Aby rozwiązać ten problem, usuwam transakcję w procedurze składowanej i używam transakcji SQL w kodzie .Net. Aby zarządzać wyjątkiem sqlException

hamid reza Heydari
źródło