В чем смысл 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 была хорошей идеей или нет, но многие люди не знают о вещах, которые я упомянул здесь, поэтому я решил, что это стоит упомянуть.