Come rilevare le eccezioni di timeout di SQLServer


117

Devo rilevare in modo specifico le eccezioni di timeout del server SQL in modo che possano essere gestite in modo diverso. So che potrei catturare la SqlException e quindi controllare se la stringa del messaggio contiene "Timeout" ma mi chiedevo se esiste un modo migliore per farlo?

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

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

Stai cercando un ConnectionTimeout o un CommandTimeout, ovvero ti aspetti che la connessione fallisca o che il comando eseguito fallisca?
edosoft

Sto cercando un CommandTimeout, che è impostato su un valore predefinito di 30 secondi, penso
brodie

Risposte:


157

Per verificare un timeout, credo che controlli il valore di ex.Number. Se è -2, allora hai una situazione di timeout.

-2 è il codice di errore per il timeout, restituito da DBNETLIB, il driver MDAC per SQL Server. Questo può essere visto scaricando Reflector e cercando in System.Data.SqlClient.TdsEnums per TIMEOUT_EXPIRED.

Il tuo codice leggerebbe:

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

Codice per dimostrare il fallimento:

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");
    }
}

Sì, è più o meno quello che sto facendo al momento, ma non è molto elegante controllare -2
brodie

12
Scarica il riflettore di Red Gate e cerca TIMEOUT_EXPIRED. Risiede in System.Data.SqlClient.TdsEnums e il suo valore è -2. : o)
Jonathan

2
Per coloro che non hanno accesso a Reflector: link
ankitk

4
@brodie Ecco perché dovresti creare una costante e puoi spiegare da dove proviene il valore "magico" in un commento sulla costante.
Jason L.

18

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

Puoi leggere anche che Thomas Weingartner ha scritto:

Timeout: SqlException.Number == -2 (Questo è un codice di errore ADO.NET)
Errore di rete generale: SqlException.Number == 11
Deadlock: SqlException.Number == 1205 (Questo è un codice di errore di SQL Server)

...

Trattiamo anche l '"errore di rete generale" come eccezione di timeout. Si verifica solo in rare circostanze, ad esempio quando la tua query di aggiornamento / inserimento / cancellazione solleverà un trigger di lunga durata.


6

Aggiornato per c # 6:

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

Molto semplice e bello da vedere !!


0

Qual è il valore per la proprietà SqlException.ErrorCode? Puoi lavorare con quello?

In caso di timeout, potrebbe essere utile controllare il codice per -2146232060 .

Lo configurerei come const statico nel codice dati.


2
Guardando i documenti per ErrorCode, mi sembra che stia segnalando errori a livello di interoperabilità. Quindi potrebbe essere più a livello di errori COM o che un provider abbia riscontrato un'eccezione (generalmente) invece di un errore specifico relativo a ciò che stai facendo.
Eric Tuttleman

@Eric è corretto: questo è un codice HRESULT per il tipo SqlException, non per l'origine dell'eccezione.
codekaizen

0

Non sono sicuro, ma quando abbiamo il timeout di esecuzione o il timeout del comando Il client invia un "ABORT" a SQL Server, quindi abbandona semplicemente l'elaborazione della query. Nessuna transazione viene annullata, nessun blocco viene rilasciato. per risolvere questo problema rimuovo la transazione in Stored-procedure e uso la transazione SQL nel mio codice .Net Per gestire sqlException


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.