webentwicklung-frage-antwort-db.com.de

Das Objekt vom Typ 'System.DBNull' kann nicht in den Typ 'System.String' umgewandelt werden

Ich habe den obigen Fehler in meiner App erhalten. Hier ist der Originalcode

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

Ich ersetzte mit

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();
    }
}

Gibt es da einen besseren Weg?

87
Saif Khan

Eine kürzere Form kann verwendet werden:

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

BEARBEITEN: Ich habe nicht auf ExecuteScalar geachtet. Es gibt wirklich null zurück, wenn das Feld im Ergebnis nicht vorhanden ist. Verwenden Sie also stattdessen:

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

Mit einer einfachen generischen Funktion können Sie dies sehr einfach machen. Mach einfach das:

return ConvertFromDBVal<string>(accountNumber);

mit der Funktion:

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 wird zurückgegeben

  • null, wenn keine Ergebnismenge vorhanden ist
  • andernfalls die erste Spalte der ersten Zeile der Ergebnismenge, die DBNull sein kann.

Wenn Sie wissen, dass die erste Spalte der Ergebnismenge eine Zeichenfolge ist, müssen Sie, um alle Basen abzudecken, sowohl nach Null als auch nach DBNull suchen. So etwas wie:

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

Der obige Code basiert auf der Tatsache, dass DBNull.ToString eine leere Zeichenfolge zurückgibt. 

Wenn accountNumber ein anderer Typ war (beispielsweise eine ganze Zahl), müssten Sie expliziter sein:

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

Wenn Sie sicher sind, dass Ihre Ergebnismenge immer mindestens eine Zeile enthält (z. B. SELECT COUNT (*) ...), können Sie die Überprüfung auf Null überspringen.

In Ihrem Fall zeigt die Fehlermeldung "Objekt vom Typ" System.DBNull "kann nicht in" System.String "umgewandelt werden" an, dass die erste Spalte Ihrer Ergebnismenge ein DBNUll-Wert ist. Dies ist von der Besetzung zur Zeichenfolge in der ersten Zeile:

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

Marc_s 'Kommentar, den Sie nicht auf DBNull überprüfen müssen. Wert ist falsch.

15
Joe

Sie können den Nullkoaleszenzoperator von C # verwenden

return accountNumber ?? string.Empty;
6
Nathan Koop

Dies ist die generische Methode, mit der ich jedes Objekt konvertieren kann, das möglicherweise ein DBNull.Value ist:

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

verwendungszweck:

var result = command.ExecuteScalar();

return result.ConvertDBNull(Convert.ToInt32);

kürzer:

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

Es gibt eine andere Möglichkeit, dieses Problem zu umgehen. Wie wäre es, wenn Sie Ihr Store-Verfahren ändern? Wenn Sie die SQL-Funktion ISNULL (Ihr Feld, "") verwenden, können Sie eine leere Zeichenfolge zurückgeben, wenn der Rückgabewert Null ist. 

Dann haben Sie Ihren sauberen Code als Originalversion.

3
Russel Yang

Ich vermute, Sie können es so machen:

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

Wenn accountNumber null ist, bedeutet das, dass es sich um DBNull und nicht um einen String handelt :)

2
ppiotrowicz

String.Concat wandelt DBNull- und Nullwerte in eine leere Zeichenfolge um.

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

    return String.Concat(accountNumber);

 }

Ich denke jedoch, Sie verlieren etwas an Code-Verständlichkeit

1
Andrea Parodi

Da ich eine Instanz habe, die nicht null ist, und wenn ich mit DBNULL verglichen habe, habe ich die Ausnahme Operator '==' cannot be applied to operands of type 'string' and 'system.dbnull' Und wenn ich versucht habe, zu NULL zu wechseln, hat es einfach nicht funktioniert (da DBNull ein Objekt ist) Auch das ist die akzeptierte Antwort.

Ich habe mich dazu entschlossen, einfach das Schlüsselwort 'is' zu verwenden. Das Ergebnis ist also sehr gut lesbar:

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

0
Remy