Невозможно передать объект типа «System.DBNull» для ввода «System.String»

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

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

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

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

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

EDIT: Не обращали внимания на ExecuteScalar. Он действительно возвращает null, если поле отсутствует в возвращаемом результате. Поэтому используйте вместо этого:

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

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

 return ConvertFromDBVal(accountNumber); 

используя функцию:

 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 вернется

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

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

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

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

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

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

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

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

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

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

Вы можете использовать оператор C # с нулевым коалесцентом

 return accountNumber ?? string.Empty; 

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

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

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

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

Применение:

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

короче:

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

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

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

Если accountNumber равно null, это означает, что это DBNull не строка 🙂

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

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

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

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

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

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

Я использую расширение, чтобы устранить эту проблему для меня, что может быть или не быть тем, чем вы занимаетесь.

Это происходит так:

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

Заметка:

Это расширение не возвращает null значения! Если элемент имеет значение null или DBNull.Value , он вернет пустую строку.

Применение:

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

Преобразовать его как

 string s = System.DBNull.value.ToString(); 
  • В C #, что происходит, когда вы вызываете метод расширения на нулевом объекте?
  • Почему статические поля не инициализируются во времени?
  • Когда был NULL макрос не 0?
  • Hibernate: Как установить значение параметра NULL-запроса в HQL?
  • Возможна ли пустая ссылка?
  • Могу ли я использовать if (указатель) вместо if (pointer! = NULL)?
  • Почему String.valueOf (null) вызывает исключение NullPointerException?
  • Отметить параметры как НЕВОЗМОЖНЫЕ в C # /. NET?
  • Ошибка: значение null в записи: incrementalFolder = null
  • Что более эффективно: if (null == variable) или if (variable == null)?
  • Почему .ToString () в нулевой строке вызывает нулевую ошибку, когда .ToString () отлично работает в nullable int с нулевым значением?
  • Давайте будем гением компьютера.