SqlException catch and handling

Q: Existe t-il un meilleur moyen de gérer les SqlExceptions?

Les exemples ci-dessous reposent sur l’interprétation du texte du message.

Eg1: J’ai un try try existant à gérer si une table n’existe pas.
Ignorez le fait que je pourrais vérifier si la table existe en premier lieu.

try { //code } catch(SqlException sqlEx) { if (sqlEx.Message.StartsWith("Invalid object name")) { //code } else throw; } 

Eg2: sans le try try montrant une exception de clé en double

 if (sqlEx.Message.StartsWith("Cannot insert duplicate key row in object")) 

Solution: Le début de mon SqlExceptionHelper

 //-- to see list of error messages: select * from sys.messages where language_id = 1033 order by message_id public static class SqlExceptionHelper { //-- rule: Add error messages in numeric order and prefix the number above the method //-- 208: Invalid object name '%.*ls'. public static bool IsInvalidObjectName(SqlException sex) { return (sex.Number == 208); } //-- 2601: Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'. The duplicate key value is %ls. public static bool IsDuplicateKey(SqlException sex) { return (sex.Number == 2601); } } 

SqlException possède une propriété Number que vous pouvez vérifier. Pour les erreurs en double, le nombre est 2601.

 catch (SqlException e) { switch (e.Number) { case 2601: // Do something. break; default: throw; } } 

Pour obtenir une liste de toutes les erreurs SQL de votre serveur, essayez ceci:

  SELECT * FROM sysmessages 

Mettre à jour

Cela peut maintenant être simplifié en C # 6.0

 catch (SqlException e) when (e.Number == 2601) { // Do something. } 

En quelque sorte, en quelque sorte. Voir la cause et la résolution des erreurs du moteur de firebase database

 class SqllErrorNumbers { public const int BadObject = 208; public const int DupKey = 2627; } try { ... } catch(SqlException sex) { foreach(SqlErrorCode err in sex.Errors) { switch (err.Number) { case SqlErrorNumber.BadObject:... case SqllErrorNumbers.DupKey: ... } } } 

Le problème est cependant qu’une bonne couche DAL serait TRY/CATCH à l’ intérieur du T-SQL (procédures stockées), avec un motif comme la gestion des exceptions et les transactions nestedes . Comme un bloc T-SQL TRY/CATCH ne peut pas générer le code d’erreur d’origine, il devra générer une nouvelle erreur, avec un code supérieur à 50000. Cela pose un problème au traitement côté client. Dans la prochaine version de SQL Server, il existe une nouvelle construction THROW qui permet de re-déclencher l’exception d’origine à partir des blocs catch T-SQL.

Il est préférable d’utiliser des codes d’erreur, vous n’avez pas à parsingr.

 try { } catch (SqlException exception) { if (exception.Number == 208) { } else throw; } 

Comment savoir que 208 devrait être utilisé:

 select message_id from sys.messages where text like 'Invalid object name%' 

Si vous voulez la liste des messages d’erreur rencontrés sur le serveur SQL, vous pouvez voir avec

 SELECT * FROM master.dbo.sysmessages 

Avec MS SQL 2008, nous pouvons répertorier les messages d’erreur pris en charge dans la table sys.messages

 SELECT * FROM sys.messages 

Si vous cherchez une meilleure façon de gérer SQLException, vous pouvez faire certaines choses. Tout d’abord, Spring.NET fait quelque chose de similaire à ce que vous recherchez (je pense). Voici un lien vers ce qu’ils font:

http://springframework.net/docs/1.2.0/reference/html/dao.html

De plus, au lieu de regarder le message, vous pouvez vérifier le code d’erreur ( sqlEx.Number ). Cela semblerait être un meilleur moyen d’identifier quelle erreur s’est produite. Le seul problème est que le numéro d’erreur renvoyé peut être différent pour chaque fournisseur de firebase database. Si vous envisagez de changer de fournisseur, vous reviendrez le gérer comme vous le souhaitez ou en créant une couche d’abstraction qui traduira ces informations pour vous.

Voici un exemple d’un gars qui a utilisé le code d’erreur et un fichier de configuration pour traduire et localiser des messages d’erreur conviviaux:

https://web.archive.org/web/20130731181042/http://weblogs.asp.net/guys/archive/2005/05/20/408142.aspx

Pour ceux d’entre vous qui peuvent lancer une erreur SQL lors de la connexion à la firebase database depuis une autre machine (par exemple, lors du chargement du formulaire), vous constaterez que lorsque vous configurez une donnée en C # qui pointe vers une firebase database SQL Server. il va configurer une connexion comme celle-ci:

 this.Table_nameTableAdapter.Fill(this.DatabaseNameDataSet.Table_name); 

Vous devrez peut-être supprimer cette ligne et la remplacer par une autre, comme une chaîne de connexion traditionnelle mentionnée sur MSDN, etc.

http://www.connectionssortingngs.com/sql-server-2008

Vous pouvez évaluer en fonction du type de gravité. Remarque: pour l’utiliser, vous devez être abonné à OnInfoMessage

 conn.InfoMessage += OnInfoMessage; conn.FireInfoMessageEventOnUserErrors = true; 

Ensuite, votre OnInfoMessage contiendrait:

 foreach(SqlError err in e.Errors) { //Informational Errors if (Between(Convert.ToInt16(err.Class), 0, 10, true)) { logger.Info(err.Message); //Errors users can correct. } else if (Between(Convert.ToInt16(err.Class), 11, 16, true)) { logger.Error(err.Message); //Errors SysAdmin can correct. } else if (Between(Convert.ToInt16(err.Class), 17, 19, true)) { logger.Error(err.Message); //Fatal Errors 20+ } else { logger.Fatal(err.Message); }} 

De cette façon, vous pouvez évaluer la gravité plutôt que le numéro d’erreur et être plus efficace. Vous pouvez trouver plus d’informations sur la sévérité ici .

 private static bool Between( int num, int lower, int upper, bool inclusive = false ) { return inclusive ? lower <= num && num <= upper : lower < num && num < upper; } 

Je travaille d’abord avec le code, C # 7 et l’entité Framework 6.0.0.0. ça marche pour moi

 Add() { bool isDuplicate = false; try { //add to database } catch (DbUpdateException ex) { if (dbUpdateException.InnerException != null) { var sqlException = dbUpdateException.InnerException.InnerException as SqlException; if(sqlException == null) isDuplicate = IsDuplicate(sqlException); } } catch (SqlException ex) { isDuplicate = IsDuplicate(ex); } if(isDuplicate){ //handle here } } bool IsDuplicate(SqlException sqlException) { switch (sqlException.Number) { case 2627: return true; default: return false; } } 

NB: ma requête pour append un élément à la firebase database se trouve dans un autre projet (couche)