Невозможно привести объект типа 'System.DBNull' к типу 'System.String` - PullRequest
92 голосов
/ 16 мая 2009

Я получил вышеуказанную ошибку в моем приложении. Вот оригинальный код

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

я заменил на

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

Есть ли лучший способ обойти это?

Ответы [ 11 ]

180 голосов
/ 16 мая 2009

С помощью простой универсальной функции вы можете сделать это очень легко. Просто сделай это:

return ConvertFromDBVal<string>(accountNumber);

с помощью функции:

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;
    }
}
76 голосов
/ 16 мая 2009

Можно использовать более короткую форму:

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

РЕДАКТИРОВАТЬ: не обращали внимания на ExecuteScalar. Это действительно возвращает нуль, если поле отсутствует в возвращаемом результате. Так что используйте вместо:

return (accountNumber == null) ? string.Empty : accountNumber.ToString() 
15 голосов
/ 16 мая 2009

ExecuteScalar вернет

  • ноль, если нет набора результатов
  • в противном случае первый столбец первой строки набора результатов, который может быть DBNull.

Если вы знаете, что первый столбец результирующего набора является строкой, то для охвата всех баз необходимо проверить как нулевой, так и DBNull. Что-то вроде:

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

Приведенный выше код основан на том факте, что DBNull.ToString возвращает пустую строку.

Если accountNumber был другого типа (скажем, целое число), то вам нужно быть более явным:

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

Если вы точно знаете, что в вашем наборе результатов всегда будет хотя бы одна строка (например, SELECT COUNT (*) ...), то вы можете пропустить проверку на нулевое значение.

В вашем случае сообщение об ошибке «Невозможно привести объект типа« System.DBNull »к типу« System.String` »указывает, что первый столбец вашего результирующего набора является значением DBNUll. Это от приведения к строке в первой строке:

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

Комментарий Marc_s о том, что вам не нужно проверять DBNull. Значение неверное.

6 голосов
/ 16 мая 2009

Вы можете использовать нулевой оператор объединения C #

return accountNumber ?? string.Empty;
3 голосов
/ 01 марта 2016

Это универсальный метод, который я использую для преобразования любого объекта, который может быть DBNull.Value:

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

использование:

var result = command.ExecuteScalar();

return result.ConvertDBNull(Convert.ToInt32);

короче:

return command
    .ExecuteScalar()
    .ConvertDBNull(Convert.ToInt32);
3 голосов
/ 31 августа 2010

Существует еще один способ обойти эту проблему. Как насчет изменения процедуры вашего магазина? используя функцию sql ISNULL (ваше поле, ""), вы можете вернуть пустую строку, если возвращаемое значение равно нулю.

Тогда у вас есть чистый код как оригинальная версия.

2 голосов
/ 16 мая 2009

Полагаю, вы можете сделать это так:

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

Если accountNumber равен нулю, это означает, что это DBNull, а не строка:)

1 голос
/ 30 августа 2010

String.Concat преобразует DBNull и нулевые значения в пустую строку.

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

    return String.Concat(accountNumber);

 }

Однако, я думаю, вы что-то теряете из-за понятности кода

0 голосов
/ 28 августа 2018

Поскольку у меня есть экземпляр, который не является нулевым, и если я сравниваю с DBNULL, я получаю исключение Operator '==' cannot be applied to operands of type 'string' and 'system.dbnull', и если я попытался изменить его для сравнения с NULL, он просто не работал (поскольку DBNull - объект), даже если это принятый ответ.

Я решил просто использовать ключевое слово "is". Таким образом, результат очень читабелен:

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

0 голосов
/ 21 февраля 2017

Конвертируйте как

string s = System.DBNull.value.ToString();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...