Como capturar exceções de tempo limite do SQLServer


117

Eu preciso capturar especificamente as exceções de tempo limite do servidor SQL para que possam ser tratadas de maneira diferente. Eu sei que poderia capturar o SqlException e, em seguida, verificar se a string da mensagem Contém "Tempo limite", mas gostaria de saber se há uma maneira melhor de fazer isso?

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

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

Você está procurando um ConnectionTimeout ou CommandTimeout, ou seja, está esperando que a conexão falhe ou o comando executado falhe?
edosoft de

Estou procurando um CommandTimeout, que é definido como um padrão de 30 segundos, eu acho
brodie

Respostas:


157

Para verificar o tempo limite, acredito que você verifique o valor de ex.Number. Se for -2, você tem uma situação de tempo limite.

-2 é o código de erro para tempo limite, retornado de DBNETLIB, o driver MDAC para SQL Server. Isso pode ser visto baixando o Reflector e procurando em System.Data.SqlClient.TdsEnums por TIMEOUT_EXPIRED.

Seu código seria:

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

Código para demonstrar falha:

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

Sim, é basicamente isso que estou fazendo no momento, mas não é muito elegante verificar -2
brodie

12
Baixe o Refletor do Red Gate e pesquise TIMEOUT_EXPIRED. Ele reside em System.Data.SqlClient.TdsEnums e seu valor é -2. : o)
Jonathan de

2
Para quem não tem acesso ao Reflector: link
ankitk

4
@brodie É por isso que você deve fazer uma constante para ela e pode explicar de onde veio o valor "mágico" em um comentário sobre a constante.
Jason L.

18

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

Você pode ler também que Thomas Weingartner escreveu:

Tempo limite: SqlException.Number == -2 (Este é um código de erro ADO.NET)
Erro de rede geral: SqlException.Number == 11
Deadlock: SqlException.Number == 1205 (Este é um código de erro do SQL Server)

...

Também tratamos o "Erro geral de rede" como uma exceção de tempo limite. Isso ocorre apenas em raras circunstâncias, por exemplo, quando sua consulta de atualização / inserção / exclusão gerará um gatilho de longa duração.


6

Atualizado para c # 6:

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

Muito simples e bonito de se olhar !!


0

Qual é o valor da propriedade SqlException.ErrorCode? Você pode trabalhar com isso?

Quando houver tempos limite, pode valer a pena verificar o código para -2146232060 .

Eu configuraria isso como uma const estática em seu código de dados.


2
Olhando para os documentos de ErrorCode, parece-me que ele está relatando erros de nível de interoperabilidade. Portanto, pode ser mais no nível de erros de COM ou que um provedor encontrou uma exceção (geralmente) em vez de um erro específico relacionado ao que você está fazendo.
Eric Tuttleman

@Eric está correto - esse é um código HRESULT para o tipo SqlException, não para a fonte da exceção.
codekaizen

0

Não tenho certeza, mas quando temos tempo limite de execução ou tempo limite de comando O cliente envia um "ABORT" para o SQL Server e simplesmente abandona o processamento da consulta. Nenhuma transação é revertida, nenhum bloqueio é liberado. para resolver este problema, eu removo a transação no procedimento armazenado e uso a transação SQL no meu código .Net para gerenciar sqlException


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.