Impossible de convertir l’object de type ‘System.DBNull’ pour taper ‘System.Ssortingng`

J’ai eu l’erreur ci-dessus dans mon application. Voici le code original

public ssortingng GetCustomerNumber(Guid id) { ssortingng accountNumber = (ssortingng)DBSqlHelperFactory.ExecuteScalar(connectionSsortingngSplendidmyApp, CommandType.StoredProcedure, "GetCustomerNumber", new SqlParameter("@id", id)); return accountNumber.ToSsortingng(); } 

J’ai remplacé par

 public ssortingng GetCustomerNumber(Guid id) { object accountNumber = (object)DBSqlHelperFactory.ExecuteScalar(connectionSsortingngSplendidCRM, CommandType.StoredProcedure, "spx_GetCustomerNumber", new SqlParameter("@id", id)); if (accountNumber is System.DBNull) { return ssortingng.Empty; } else { return accountNumber.ToSsortingng(); } } 

Y a-t-il une meilleure façon de contourner cela?

Une forme plus courte peut être utilisée:

 return (accountNumber == DBNull.Value) ? ssortingng.Empty : accountNumber.ToSsortingng() 

EDIT: Je n’ai pas fait attention à ExecuteScalar. Il renvoie vraiment null si le champ est absent dans le résultat de retour. Donc, utilisez plutôt:

 return (accountNumber == null) ? ssortingng.Empty : accountNumber.ToSsortingng() 

Avec une fonction générique simple, vous pouvez rendre cela très facile. Faites ceci:

 return ConvertFromDBVal(accountNumber); 

en utilisant la fonction:

 public static T ConvertFromDBVal(object obj) { if (obj == null || obj == DBNull.Value) { return default(T); // returns the default value for the type } else { return (T)obj; } } 

ExecuteScalar reviendra

  • null s’il n’y a pas de résultat
  • sinon la première colonne de la première ligne du jeu de résultats, qui peut être DBNull.

Si vous savez que la première colonne du jeu de résultats est une chaîne, alors pour couvrir toutes les bases, vous devez rechercher les valeurs NULL et DBNull. Quelque chose comme:

 object accountNumber = ...ExecuteScalar(...); return (accountNumber == null) ? Ssortingng.Empty : accountNumber.ToSsortingng(); 

Le code ci-dessus repose sur le fait que DBNull.ToSsortingng renvoie une chaîne vide.

Si accountNumber était un autre type (par exemple un entier), vous devrez alors être plus explicite:

 object accountNumber = ...ExecuteScalar(...); return (accountNumber == null || Convert.IsDBNull(accountNumber) ? (int) accountNumber : 0; 

Si vous êtes certain que votre jeu de résultats aura toujours au moins une ligne (par exemple, SELECT COUNT (*) …), vous pouvez ignorer la vérification de null.

Dans votre cas, le message d’erreur “Impossible de convertir l’object de type ‘System.DBNull’ pour taper ‘System.Ssortingng`” indique que la première colonne de votre jeu de résultats est une valeur DBNUll. Ceci est de la dissortingbution à la chaîne sur la première ligne:

 ssortingng accountNumber = (ssortingng) ... ExecuteScalar(...); 

Le commentaire de Marc_s que vous n’avez pas besoin de vérifier DBNull.Value est faux.

Vous pouvez utiliser l’opérateur de coalescence null de C #

 return accountNumber ?? ssortingng.Empty; 

Il existe un autre moyen de contourner ce problème. Que diriez-vous de modifier votre procédure de magasin? en utilisant ISNULL (votre champ, “”), la fonction SQL, vous pouvez retourner une chaîne vide si la valeur de retour est null.

Ensuite, vous avez votre code propre en version originale.

C’est la méthode générique que j’utilise pour convertir tout object pouvant être un DBNull.Value:

 public static T ConvertDBNull(object value, Func conversionFunction) { return conversionFunction(value == DBNull.Value ? null : value); } 

usage:

 var result = command.ExecuteScalar(); return result.ConvertDBNull(Convert.ToInt32); 

plus court:

 return command .ExecuteScalar() .ConvertDBNull(Convert.ToInt32); 

Je suppose que vous pouvez le faire comme ceci:

 ssortingng accountNumber = DBSqlHelperFactory.ExecuteScalar(...) as ssortingng; 

Si accountNumber est null, cela signifie que DBNull n’est pas une chaîne 🙂

Ssortingng.Concat transforme les valeurs DBNull et null en une chaîne vide.

 public ssortingng GetCustomerNumber(Guid id) { object accountNumber = (object)DBSqlHelperFactory.ExecuteScalar(connectionSsortingngSplendidCRM, CommandType.StoredProcedure, "spx_GetCustomerNumber", new SqlParameter("@id", id)); return Ssortingng.Concat(accountNumber); } 

Cependant, je pense que vous perdez quelque chose sur la compréhensibilité du code

Depuis que j’ai une instance qui n’est pas nulle et que j’ai comparé à DBNULL, j’ai eu l’ Operator '==' cannot be applied to operands of type 'ssortingng' and 'system.dbnull' , et si j’ai essayé de changer pour comparer à NULL, cela n’a tout simplement pas fonctionné (puisque DBNull est un object) même si c’est la réponse acceptée.

J’ai décidé d’utiliser simplement le mot clé ‘is’. Le résultat est donc très lisible:

data = (item is DBNull) ? Ssortingng.Empty : item

J’utilise une extension pour éliminer ce problème pour moi, ce qui peut être ou ne pas être ce que vous recherchez.

Ça va comme ça:

 public static class Extensions { public Ssortingng TrimSsortingng(this object item) { return Ssortingng.Format("{0}", item).Trim(); } } 

Remarque:

Cette extension ne renvoie pas de valeurs null ! Si l’élément est null ou DBNull.Value , il retournera une chaîne vide.

Usage:

 public ssortingng GetCustomerNumber(Guid id) { var obj = DBSqlHelperFactory.ExecuteScalar( connectionSsortingngSplendidmyApp, CommandType.StoredProcedure, "GetCustomerNumber", new SqlParameter("@id", id) ); return obj.TrimSsortingng(); } 

Convertissez-le comme

 ssortingng s = System.DBNull.value.ToSsortingng();