Cómo detectar excepciones de tiempo de espera de SQLServer

117

Necesito detectar específicamente las excepciones de tiempo de espera del servidor SQL para que puedan manejarse de manera diferente. Sé que podría detectar la SqlException y luego verificar si la cadena del mensaje contiene "Timeout", pero me preguntaba si hay una mejor manera de hacerlo.

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

    if (ex.Message.Contains("Timeout"))
    {
         //handle timeout
    }
    else
    {
         throw;
    }
}
Brodie
fuente
¿Está buscando un ConnectionTimeout o un CommandTimeout, es decir, espera que la conexión falle o que falle el comando ejecutado?
edosoft
Estoy buscando un CommandTimeout, que está configurado en un valor predeterminado de 30 segundos, creo
brodie

Respuestas:

157

Para verificar un tiempo de espera, creo que verifica el valor de, por ejemplo, Número. Si es -2, entonces tiene una situación de tiempo de espera.

-2 es el código de error para el tiempo de espera, devuelto por DBNETLIB, el controlador MDAC para SQL Server. Esto se puede ver descargando Reflector y buscando en System.Data.SqlClient.TdsEnums para TIMEOUT_EXPIRED.

Su código leería:

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

Código para demostrar falla:

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
fuente
Sí, eso es más o menos lo que estoy haciendo en este momento, pero no es muy elegante verificar -2
brodie
12
Descarga Reflector de Red Gate y busca TIMEOUT_EXPIRED. Vive en System.Data.SqlClient.TdsEnums y su valor es -2. : o)
Jonathan
2
Para aquellos que no tienen acceso a Reflector: enlace
ankitk
4
@brodie Es por eso que debe hacer una constante para ello y puede explicar de dónde vino el valor "mágico" en un comentario sobre la constante.
Jason L.
18

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

También puede leer que Thomas Weingartner escribió:

Tiempo de espera: SqlException.Number == -2 (Este es un código de error de ADO.NET)
Error de red general: SqlException.Number == 11
Interbloqueo: SqlException.Number == 1205 (Este es un código de error de SQL Server)

...

También manejamos el "Error general de la red" como una excepción de tiempo de espera. Solo ocurre en circunstancias excepcionales, por ejemplo, cuando su consulta de actualización / inserción / eliminación generará un activador de larga duración.

Roland Pihlakas
fuente
6

Actualizado para c # 6:

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

Muy simple y agradable a la vista !!

John Evans
fuente
0

¿Cuál es el valor de la propiedad SqlException.ErrorCode? ¿Puedes trabajar con eso?

Cuando tenga tiempos de espera, puede que valga la pena comprobar el código -2146232060 .

Configuraría esto como una constante estática en su código de datos.

Rob Cooper
fuente
2
Al mirar los documentos de ErrorCode, me parece que está informando errores de nivel de interoperabilidad. Por lo tanto, puede ser más en el nivel de errores COM o que un proveedor encontró una excepción (generalmente) en lugar de un error específico relacionado con lo que está haciendo.
Eric Tuttleman
@Eric es correcto: es un código HRESULT para el tipo SqlException, no para el origen de la excepción.
Codekaizen
0

No estoy seguro, pero cuando hemos ejecutado el tiempo de espera o el tiempo de espera del comando, el cliente envía un "ABORT" a SQL Server y luego simplemente abandona el procesamiento de la consulta. No se revierte ninguna transacción, no se liberan bloqueos. para resolver este problema, elimino la transacción en el procedimiento almacenado y uso la transacción SQL en mi código .Net para administrar sqlException

hamid reza heydari
fuente