À partir d'une application .NET 3.5 / C #, je voudrais attraper, SqlException
mais uniquement si cela est causé par des blocages sur une instance SQL Server 2008.
Le message d'erreur typique est Transaction (Process ID 58) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Pourtant, cela ne semble pas être un code d'erreur documenté pour cette exception.
Le filtrage des exceptions contre la présence du mot-clé de blocage dans leur message semble une manière très moche de parvenir à ce comportement. Est-ce que quelqu'un connaît la bonne façon de procéder?
.net
sql-server-2008
deadlock
try-catch
sqlexception
Joannes Vermorel
la source
la source
select * from master.dbo.sysmessages where error=1205
Réponses:
Le code d'erreur spécifique à Microsft SQL Server pour un blocage est 1205, vous devez donc gérer l'exception SqlException et vérifier cela. Donc, par exemple, si pour tous les autres types de SqlException, vous voulez que la bulle augmente l'exception:
Ou, en utilisant le filtrage des exceptions disponible en C # 6
Une chose pratique à faire pour trouver le code d'erreur SQL réel pour un message donné est de rechercher dans sys.messages dans SQL Server.
par exemple
Une autre façon de gérer les blocages (à partir de SQL Server 2005 et supérieur) consiste à le faire dans une procédure stockée en utilisant le support TRY ... CATCH:
Il existe un exemple complet ici dans MSDN de la façon d'implémenter la logique de relance de blocage uniquement dans SQL.
la source
SqlException
peut être enveloppé dans un autre. Nous pouvons donc avoir besoin d'attraper n'importe quel type d'exception et de les vérifier, puis, s'ils ne sont pas directement une exception de blocage, vérifiez récursivement leurInnerException
.Parce que je suppose que vous voulez peut-être détecter les blocages, pour pouvoir réessayer l'opération qui a échoué, j'aime vous avertir pour un petit coup. J'espère que vous m'excuserez d'être un peu hors sujet ici.
Un blocage détecté par la base de données annulera efficacement la transaction dans laquelle vous étiez en cours d'exécution (le cas échéant), tandis que la connexion est maintenue ouverte dans .NET. Réessayer cette opération (dans cette même connexion) signifie qu'elle sera exécutée dans un contexte sans transaction et cela pourrait entraîner une corruption des données.
Il est important d'en être conscient. Il est préférable de considérer la connexion complète vouée à l'échec en cas d'échec causé par SQL. La relance de l'opération ne peut être effectuée qu'au niveau où la transaction est définie (en recréant cette transaction et sa connexion).
Ainsi, lorsque vous réessayez une opération qui a échoué, assurez-vous d'ouvrir une toute nouvelle connexion et de démarrer une nouvelle transaction.
la source
Voici un moyen C # 6 de détecter les blocages.
Assurez-vous que ce try..catch entoure toute votre transaction. Selon @Steven (voir sa réponse pour plus de détails), lorsque la commande sql échoue en raison du blocage, elle provoque l'annulation de la transaction et, si vous ne recréez pas la transaction, votre nouvelle tentative s'exécutera en dehors du contexte de la transaction et peut entraîner des incohérences dans les données.
la source