В чем смысл DBNull?
в .NET есть null
ссылка, которая используется везде, чтобы обозначить, что ссылка на объект пуста, а затем есть DBNull
, который используется драйверами базы данных (и несколькими другими) для обозначения... почти то же самое. Естественно, это создает много путаницы, и процедуры преобразования должны быть сбиты и т. д.
так почему же оригинальные авторы .NET решили сделать это? Для меня это не имеет смысла. Их документация не имеет смысла либо:
класс DBNull представляет несуществующее значение. Например, в базе данных столбец в строке таблицы может не содержать никаких данных. То есть столбец считается вообще не существующим, а просто не имеющим значения. Объект DBNull представляет несуществующий столбец. Кроме того, com-взаимодействие использует класс DBNull для различения варианта VT_NULL, который указывает на несуществующее значение, и варианта VT_EMPTY, который указывает на неопределенное значение.
что это за дерьмо о "колонке не существует"? Столбец существует, он просто не имеет значения для конкретной строки. Если бы он не существовал, я бы получил исключение, пытаясь получить доступ к конкретной ячейке, а не DBNull
! Я могу понять необходимость различать VT_NULL
и VT_EMPTY
, но тогда почему бы не сделать COMEmpty
вместо класса? Это было бы гораздо аккуратнее подходит для всей .NET framework.
Я что-то пропустила? Может ли кто-нибудь пролить немного света почему DBNull
был изобретен и какие проблемы он помогает решить?
5 ответов
дело в том, что в определенных ситуациях существует разница между значением базы данных null и .NET Null.
например. Если вы используете ExecuteScalar (который возвращает первый столбец первой строки в результирующем наборе) и получаете null, это означает, что выполненный SQL не вернул никаких значений. Если вы получите DBNull обратно, это означает, что значение было возвращено SQL, и оно было NULL. Ты должен уметь отличать одно от другого.
я собираюсь не согласиться с тенденцией здесь. Я пойду на запись:
я не согласен с этим
DBNull
служит любой полезной цели; это добавляет ненужную путаницу, не внося практически никакой ценности.
аргумент часто выдвигается, что null
является недопустимой ссылкой, и это DBNull
является нулевым шаблоном объекта;тоже верно. Например:
int? x = null;
это не "недопустимая ссылка"; это null
значение. Действительно null
означает все, что вы хотите, и, честно говоря, у меня нет абсолютно никаких проблем с значениями, которые могут быть null
(действительно, даже в SQL нам нужно правильно работать с null
- здесь ничего не меняется). Равным образом, " шаблон нулевого объекта "имеет смысл только в том случае, если вы действительно рассматриваете его как объект в терминах ООП, но если у нас есть значение, которое может быть" нашим значением или или DataRow.IsNull
- ни один из которых на самом деле не требует DBNull
существовать в терминах API
DBNull
терпит неудачу в терминах null-коалесцирования;value ?? defaultValue
не работает, если значение DBNull
DBNull.Value
не может использоваться в необязательных параметрах, так как это не константаDBNull
идентичны семантика null
; в частности, DBNull
фактически составляет DBNull
- так это не выполните задание представления SQL semanticobject
DBNull
, вы могли бы также протестировать для just null
null
значение не отправляется... Ну, вот идея: если вам не нужен параметр - не добавлять его в коллекцию параметров
DBNull
, за исключением как дополнительная досада при разговоре с ADO.NET кодтолько даже отдаленно убедительный аргумент у меня когда-нибудь видели, чтобы оправдать существование такого значения в DataTable
, при передаче значений для создания новой строки; a null
означает "использовать значение по умолчанию", a DBNull
является явно нулевым-откровенно говоря, этот API мог бы иметь конкретное лечение для этого случая-мнимое DataRow.DefaultValue
например, было бы намного лучше, чем вводить DBNull.Value
это заражает обширные полосы кода без причины.
кроме того,ExecuteScalar
сценарий... в лучшем случае тонкая; если вы выполняете скалярный метод, вы ожидал результат. В сценарии, где нет строк, returning null
не кажется слишком ужасный. Если вам абсолютно необходимо устранить неоднозначность между "нет строк" и "один единственный возвращаемый null", есть API reader.
я на самом деле интересно, если все это связано с двумя вещи:
- использовать слово
Nothing
вместо чего-то, включающего "null" в VB - будучи в состоянии нам
if(value is DBNull)
синтаксис, который "выглядит так же, как SQL", а не oh-so-trickyif(value==null)
резюме:
имея 3 варианта (null
, DBNull
, или фактическое значение) полезно только в том случае, если есть подлинный пример, когда вам нужно устранить двусмысленность между 3 различными случаями. Я еще не видел случая, где мне нужно чтобы представить два разных состояния "null", so DBNull
является полностью избыточным, учитывая, что null
уже существует и имеет гораздо лучшую поддержку языка и среды выполнения.
вы используете DBNull для отсутствующих данных. Null в языке .NET означает, что для объекта/переменной нет указателя.
DBNull отсутствуют данные:http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx
влияние отсутствующих данных на статистику:
есть некоторые различия между CLR null и DBNull. Во-первых, null в реляционных базах данных имеет различную семантику "равно": null не равно null. CLR null равно null.
но я подозреваю, что основная причина заключается в том, как значения по умолчанию параметров работают в SQL server и реализации поставщика.
чтобы увидеть разницу, создайте процедуру с параметром, имеющим значение по умолчанию:
CREATE PROC [Echo] @s varchar(MAX) = 'hello'
AS
SELECT @s [Echo]
хорошо структурированный DAL код должен отделять создание команды от использования (чтобы использовать одну и ту же команду много раз, например, чтобы вызвать хранимую процедуру много раз эффективно). Напишите метод, который возвращает SqlCommand, представляющий вышеуказанную процедуру:
SqlCommand GetEchoProc()
{
var cmd = new SqlCommand("Echo");
cmd.Parameters.Add("@s", SqlDbType.VarChar);
return cmd;
}
Если теперь вы вызовете команду без установки параметра @s или установите ее значение в (CLR) null, она будет использовать значение по умолчанию "hello". Если, с другой стороны, вы установили значение параметра в DBNull.Значение, оно будет использовать это и echo Значение dbnull.Значение.
поскольку есть два разных результата с использованием CLR null или database null в качестве значения параметра, вы не можете представлять оба случая только с одним из них. Если CLR null должен быть единственным, он должен работать так, как DBNull.Значение сегодня. Один из способов указать поставщику "я хочу использовать значение по умолчанию" может заключаться в том, чтобы вообще не объявлять параметр (параметр со значением по умолчанию, конечно, имеет смысл описывать как "необязательный параметр"), но в сценарии если объект command кэшируется и используется повторно, это приводит к удалению и повторному добавлению параметра.
Я не уверен, считаю ли я, что DBNull была хорошей идеей или нет, но многие люди не знают о вещах, которые я упомянул здесь, поэтому я решил, что это стоит упомянуть.