Смущен пустыми строками и DBNull - PullRequest
4 голосов
/ 08 ноября 2011

Я смотрю код для программы .net, над которой я работаю.Предыдущий автор программы дал мне код более года назад.Внезапно я вижу исключение, которое выдается из кода, к которому я не прикасался:

if ((string)row["LevelName"] != "ABC")

Исключение: «Невозможно привести объект типа« System.DBNull »к типу« System.String ».

Я думал, что строка имеет тип данных, допускающий значение NULL, так как я могу получить это исключение?

Ответы [ 5 ]

9 голосов
/ 08 ноября 2011

Я считаю, что вы ищете:

if ((row["LevelName"] as String) != "ABC")

Не существует неявного приведения между DBNull и String.

Возможно, раньше это работало, потому что просто не былоNULL в этом столбце в вашей базе данных.Возможно, некоторые данные были повреждены, или кто-то изменил ограничение NOT NULL для таблицы.

Обычно, если вы явно что-то приводите, вам лучше убедиться, что они имеют совместимые динамические типы, в противном случае выдается исключение.Оператор as в основном говорит: «Приведите его к этому, если это возможно, иначе логическое значение равно нулю».Очевидно, что оператор as работает только со ссылочными типами, поскольку структуры не могут быть нулевыми.

7 голосов
/ 08 ноября 2011

DBNull - это его собственный класс, который содержит единственный экземпляр самого себя в свойстве с именем Значение .DBNull.Value не равно нулю, так как это ссылка на экземпляр этого класса.

Большинство, если не все обертки базы данных, вернут DBNull.Value вместо null, когда значение отсутствует.Одна из причин этого заключается в том, что возвращение действительного null может означать, что строки вообще нет, а не просто нулевое значение в столбце (хотя это зависит от того, какие объекты вы используете для получения значений).

Как правило, оператор as очень полезен с DBNull и может использоваться с любым типом, допускающим обнуление (включая string).

string str = reader["Name"] as string;
int? i = reader["Age"] as int?;

Это также может бытьСтоит отметить, что оператор ?? очень полезен и здесь, когда вам нужен необнуляемый тип значения (хотя это выглядит не слишком красиво).

int i = reader["Age"] as int? ?? -1;

Я считаю,это очень удобно, как небольшой сценарий "просто в случае" в предложении LINQ select.

4 голосов
/ 08 ноября 2011

DBNull означает, что в данном столбце базы данных нет данных.Это может произойти, если в базе данных создается новая запись, но столбцу «LevelName» не назначено значение.

DBNull - это не то же самое, что ссылка на пустой объект или переменная пустой строки.DBNull означает, что данные столбца никогда не задавались.Если для столбца «LevelName» назначено значение NULL, то этот столбец был инициализирован и будет возвращать значение NULL (не DBNull).

3 голосов
/ 08 ноября 2011

DBNull представляет нулевое значение в базе данных.Это не то же самое, что нулевой .NET, который указывает на пустую ссылку.

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

Да, строка являетсяNullable, но вы бросаете dbnull в строку.Вы должны проверить наличие dbnull и заменить его на null, если он там есть.

2 голосов
/ 08 ноября 2011

Существует разница между .NET null и DBNull.Value. Здесь вы можете увидеть, что такое класс DBNull и поле Значение этого класса.

Вы должны быть в состоянии сделать что-то вроде этого:

if (row["LevelName"].Value == DBNull.Value)
    return false;
else if (row["LevelName"].ToString() != "ABC")
    // do something
    // ....
...