Comment intercepter les exceptions de délai d'expiration SQLServer

117

J'ai besoin d'attraper spécifiquement les exceptions de délai d'expiration du serveur SQL afin qu'elles puissent être traitées différemment. Je sais que je pourrais attraper le SqlException et puis vérifier si la chaîne de message contient "Timeout" mais je me demandais s'il y avait une meilleure façon de le faire?

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

    if (ex.Message.Contains("Timeout"))
    {
         //handle timeout
    }
    else
    {
         throw;
    }
}
brodie
la source
Cherchez-vous un ConnectionTimeout ou un CommandTimeout, c'est-à-dire vous attendez-vous à ce que la connexion échoue ou que la commande exécutée échoue?
edosoft
Je recherche un CommandTimeout, qui est défini sur une valeur par défaut de 30 secondes, je pense
brodie

Réponses:

157

Pour vérifier un délai d'attente, je crois que vous vérifiez la valeur de ex.Number. Si c'est -2, alors vous avez une situation de timeout.

-2 est le code d'erreur pour le délai d'expiration, renvoyé par DBNETLIB, le pilote MDAC pour SQL Server. Cela peut être vu en téléchargeant Reflector et en recherchant sous System.Data.SqlClient.TdsEnums pour TIMEOUT_EXPIRED.

Votre code lirait:

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

Code pour démontrer l'échec:

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
la source
Oui, c'est à peu près ce que je fais en ce moment, mais ce n'est pas très élégant vérifier pour -2
brodie
12
Téléchargez le réflecteur de Red Gate et recherchez TIMEOUT_EXPIRED. Il réside dans System.Data.SqlClient.TdsEnums et sa valeur est -2. : o)
Jonathan
2
Pour ceux qui n'ont pas accès à Reflector: lien
ankitk
4
@brodie C'est pourquoi vous devriez lui faire une constante et vous pouvez expliquer d'où vient la valeur "magique" dans un commentaire sur la constante.
Jason L.
18

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

Vous pouvez également lire que Thomas Weingartner a écrit:

Timeout: SqlException.Number == -2 (il s'agit d'un code d'erreur ADO.NET)
Erreur réseau générale: SqlException.Number == 11
Blocage: SqlException.Number == 1205 (il s'agit d'un code d'erreur SQL Server)

...

Nous traitons également l '"Erreur réseau générale" comme une exception de délai. Cela ne se produit que dans de rares circonstances, par exemple lorsque votre requête de mise à jour / insertion / suppression déclenchera un déclencheur de longue durée.

Roland Pihlakas
la source
6

Mis à jour pour c # 6:

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

Très simple et agréable à regarder !!

John Evans
la source
0

Quelle est la valeur de la propriété SqlException.ErrorCode? Pouvez-vous travailler avec ça?

En cas d' expiration de délai, il peut être utile de vérifier le code -2146232060 .

Je définirais cela comme un const statique dans votre code de données.

Rob Cooper
la source
2
En regardant la documentation pour ErrorCode, il me semble que cela signale des erreurs de niveau Interop. Cela peut donc être plus au niveau des erreurs COM ou qu'un fournisseur a rencontré une exception (généralement) au lieu d'une erreur spécifique liée à ce que vous faites.
Eric Tuttleman
@Eric est correct - c'est un code HRESULT pour le type SqlException, pas pour la source de l'exception.
codekaizen
0

Je ne suis pas sûr mais lorsque nous avons expiré le délai d'exécution ou le délai de commande Le client envoie un "ABORT" à SQL Server puis abandonne simplement le traitement de la requête. Aucune transaction n'est annulée, aucun verrou n'est libéré. pour résoudre ce problème, je supprime la transaction dans la procédure stockée et utilise la transaction SQL dans mon code .Net Pour gérer sqlException

hamid reza Heydari
la source