web-dev-qa-db-fra.com

Impossible de convertir l'objet de type 'System.DBNull' en 'System.String`

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

public string GetCustomerNumber(Guid id)
{
     string accountNumber = 
          (string)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidmyApp, 
                          CommandType.StoredProcedure, 
                          "GetCustomerNumber", 
                          new SqlParameter("@id", id));
     return accountNumber.ToString();
 }

J'ai remplacé par

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

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

87
Saif Khan

Un formulaire plus court peut être utilisé:

return (accountNumber == DBNull.Value) ? string.Empty : accountNumber.ToString()

EDIT: N'a pas fait attention à ExecuteScalar. Il renvoie vraiment null si le champ est absent du résultat. Alors utilisez plutôt:

return (accountNumber == null) ? string.Empty : accountNumber.ToString() 
73
User

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

return ConvertFromDBVal<string>(accountNumber);

en utilisant la fonction:

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

ExecuteScalar retournera

  • 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 résultat est une chaîne, pour couvrir toutes les bases, vous devez rechercher null et DBNull. Quelque chose comme:

object accountNumber = ...ExecuteScalar(...);
return (accountNumber == null) ? String.Empty : accountNumber.ToString();

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

Si accountNumber est un autre type (par exemple, un entier), vous devez ê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 comportera toujours au moins une ligne (par exemple, SELECT COUNT (*) ...), vous pouvez ignorer la vérification de la valeur null.

Dans votre cas, le message d'erreur "Impossible de convertir un objet de type 'System.DBNull' en un type 'System.String`" indique que la première colonne de votre jeu de résultats est une valeur DBNUll. Ceci est du casting à la chaîne sur la première ligne:

string accountNumber = (string) ... ExecuteScalar(...);

Marc_s a déclaré qu'il n'était pas nécessaire de rechercher DBNull.Value.

15
Joe

Vous pouvez utiliser l'opérateur de coalescence nul de C #

return accountNumber ?? string.Empty;
6
Nathan Koop

C'est la méthode générique que j'utilise pour convertir tout objet pouvant être un fichier DBNull.Value

public static T ConvertDBNull<T>(object value, Func<object, T> 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);
3
Heras

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

Ensuite, vous avez votre code propre en version originale.

3
Russel Yang

Je suppose que tu peux le faire comme ça:

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

Si accountNumber est null, cela signifie que DBNull n'est pas une chaîne :)

2
ppiotrowicz

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

public string GetCustomerNumber(Guid id)
{
   object accountNumber =  
          (object)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidCRM, 
                                CommandType.StoredProcedure, 
                                "spx_GetCustomerNumber", 
                                new SqlParameter("@id", id));

    return String.Concat(accountNumber);

 }

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

1
Andrea Parodi