So fangen Sie SQLServer-Timeout-Ausnahmen ab


117

Ich muss speziell SQL Server-Timeout-Ausnahmen abfangen, damit sie unterschiedlich behandelt werden können. Ich weiß, dass ich die SqlException abfangen und dann überprüfen kann, ob die Nachrichtenzeichenfolge "Timeout" enthält, habe mich aber gefragt, ob es einen besseren Weg gibt, dies zu tun.

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

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

Suchen Sie nach einem ConnectionTimeout oder einem CommandTimeout, dh erwarten Sie, dass die Verbindung fehlschlägt oder der ausgeführte Befehl fehlschlägt?
Edosoft

Ich suche nach einem CommandTimeout, das auf einen Standard von 30 Sekunden eingestellt ist, glaube ich
brodie

Antworten:


157

Ich glaube, Sie überprüfen den Wert von ex.Number, um nach einer Zeitüberschreitung zu suchen. Wenn es -2 ist, haben Sie eine Zeitüberschreitungssituation.

-2 ist der Fehlercode für das Zeitlimit, der von DBNETLIB, dem MDAC-Treiber für SQL Server, zurückgegeben wird. Dies können Sie sehen, indem Sie Reflector herunterladen und unter System.Data.SqlClient.TdsEnums nach TIMEOUT_EXPIRED suchen.

Ihr Code würde lauten:

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

Code zum Nachweis eines Fehlers:

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

Ja, das ist ziemlich genau das, was ich im Moment mache, aber es ist nicht sehr elegant, nach -2 zu
suchen

12
Laden Sie den Reflektor von Red Gate herunter und suchen Sie nach TIMEOUT_EXPIRED. Es befindet sich in System.Data.SqlClient.TdsEnums und hat einen Wert von -2. : o)
Jonathan

2
Für diejenigen, die keinen Zugang zu Reflector haben: link
ankitk

4
@brodie Deshalb solltest du eine Konstante dafür machen und kannst in einem Kommentar zur Konstante erklären, woher der "magische" Wert stammt.
Jason L.

18

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

Sie können auch lesen, dass Thomas Weingartner schrieb:

Zeitüberschreitung: SqlException.Number == -2 (Dies ist ein ADO.NET-Fehlercode)
Allgemeiner Netzwerkfehler: SqlException.Number == 11
Deadlock: SqlException.Number == 1205 (Dies ist ein SQL Server-Fehlercode)

...

Wir behandeln den "Allgemeinen Netzwerkfehler" auch als Timeout-Ausnahme. Dies tritt nur in seltenen Fällen auf, z. B. wenn Ihre Abfrage zum Aktualisieren / Einfügen / Löschen einen lang laufenden Auslöser auslöst.


6

Aktualisiert für c # 6:

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

Sehr einfach und schön anzusehen !!


0

Was ist der Wert für die SqlException.ErrorCode-Eigenschaft? Kannst du damit arbeiten?

Bei Zeitüberschreitungen kann es sich lohnen, den Code auf -2146232060 zu überprüfen .

Ich würde dies als statische Konstante in Ihrem Datencode einrichten.


2
Wenn ich mir die Dokumente für ErrorCode anschaue, scheint es mir, dass es Interop-Level-Fehler meldet. Es kann also eher auf der Ebene der COM-Fehler liegen oder dass ein Anbieter (im Allgemeinen) auf eine Ausnahme gestoßen ist, anstatt auf einen bestimmten Fehler in Bezug auf Ihre Aktivitäten.
Eric Tuttleman

@Eric ist korrekt - das ist ein HRESULT-Code für den SqlException-Typ, nicht für die Quelle der Ausnahme.
Codekaizen

0

Ich bin nicht sicher, aber wenn wir eine Zeitüberschreitung bei der Ausführung oder eine Befehlszeitüberschreitung haben Der Client sendet ein "ABORT" an SQL Server und gibt dann einfach die Abfrageverarbeitung auf. Es wird keine Transaktion zurückgesetzt, es werden keine Sperren freigegeben. Um dieses Problem zu lösen, entferne ich die Transaktion in der gespeicherten Prozedur und verwende die SQL-Transaktion in meinem .NET-Code, um die sqlException zu verwalten


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.