Подтвердить что ты не робот

Нулевые типы в строго типизированных данных/наборах данных - обходные пути?

Сильно типизированные DataTables поддерживают типы полей с "нулевым" значением, за исключением того, что конструктор не позволит вам изменить параметр "allow nulls" для любых полей типа значения. (т.е. типы String допускают значение NULL, но int нет).

Обходным решением является вызов IsMyFieldNull() в любое время, когда вы хотите получить Myfield. Если вы обращаетесь к MyField, когда он содержит нуль, он вызывает перехват.

Это массивная головная боль, в дополнение к возникновению множества ошибок во время выполнения, когда появление нулевой информации может привести к сбою приложения. Я много лет жаловался на Microsoft, но каждый новый релиз Visual Studio по-прежнему не позволяет использовать типы допустимых значений.

Мой вопрос: кто-нибудь знает о причудливых методах расширения, которые могут быть использованы для устранения этого основного недостатка?

4b9b3361

Ответ 1

Если вы используете .Net 3.5 или выше, возможно, эти расширения могут вам пригодиться: http://msdn.microsoft.com/en-us/library/system.data.datarowextensions.field.aspx

В соответствии с документацией он полностью поддерживает типы с нулевым значением. Он позволяет использовать такие конструкции, как

MyRow.Field<int?>("MyField") 

и если вы назначаете его или из существующей переменной правильного типа, компилятор может вывести тип автоматически, и вы можете оставить спецификатор типа, сделав его коротким, как

int? myVar = MyRow.Field("MyField");
MyRow.Field("MyField") = myVar;

Все еще не идеальный, но гораздо более разборчивый, чем использование IsMyFieldNull() и т.д. везде.

О, и если вы хотите быть более уверенным в том, что касается имен имен орфографических имен, вы можете использовать такие вещи, как

MyRow.Field(MyTable.MyFieldColumn)

Не забудьте добавить ссылку на System.Data.DataSetExtensions.

Ответ 2

В VS 2008 вы можете просто ввести "0" в свойстве nullvalue.
Если вы используете vs2005, вы должны сделать это с помощью XML-редактора. Вы должны добавить msprop:nullValue="0" в качестве атрибута в столбец.

Ответ 3

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

Если вы установите для свойства "NullValue" в столбце значение "-1" вместо "(исключение Throw)", свойство вернет -1, когда столбец будет null, а не выбрасывает исключение. Вы все равно должны установить столбец, чтобы разрешить null.

В качестве альтернативы вы всегда можете установить тип данных в "System.Object" и разрешить nulls = true. Вы можете получить доступ к значению столбца без использования метода "IsMyFieldNull()". Значение столбца будет "System.DbNull.Value", если столбец равен NULL. Если вам не нравится использовать "System.DbNull.Value", вы можете установить для свойства "NullValue" значение "(Nothing)" вместо "(исключение Throw)", а затем сравнить объект с нулевой ссылкой.

Ответ 4

Вы можете сделать это: установите AllowDbNull в значение true, если оно не установлено; DefaultValue остается включенным; NullValue остается включенным (исключение Throw). Затем из кода, когда вы хотите установить нулевой столбец, вы можете использовать встроенный метод Set_Column_Null(). Посмотрите мой пример:

if (entry.PosX.HasValue)
    newRow.PosX = entry.PosX.Value;
else
    newRow.SetPosXNull(); 

Ответ 5

Мне просто нужно было найти работу для этого. Мне нужно было изменить старый код для веб-страницы, написанной для ASP.NET 2.0. На странице используется Telerik RadMenu, элемент управления меню. Этот компонент требует, чтобы корневые элементы имели соответствующие DBNull-значения (для parentID). Итак, когда я скомпилировал старый код, компонент RadMenu дал мне много проблем. Первые исключения в отношении ограничений, тогда он не понимал, какие элементы являются корневыми элементами, и все это выглядело ужасно.

Но я решил это, и это то, что сработало для меня.

На странице "Свойства" столбца ParentID в дизайнере адаптера таблицы я использовал:  - AllowDBNull: true  - DefaultValue: -1 (-1 - это значение, которое обычно не встречается для этого столбца) Свойство NullValue оставалось в "Throw Exception", потому что меня невозможно было изменить.

И в коде, использующем значения из адаптера таблицы, я использовал эту конструкцию (код VB.NET, а не С#, поскольку этот вопрос отмечен):

Dim MenuBarTable As DAL.Page.MenuBarDataTable 'The Table Adapter
MenuBarTable = PageObj.GetMenuBar()  'The generated Get function 
MenuBarTable.ParentIDColumn.AllowDBNull = True 

    For Each row As Page.MenuBarRow In MenuBarTable.Rows
        If row.IsParentIDNull() Then 
            row.SetParentIDNull() 
        End If
    Next

Код, созданный для адаптеров таблицы, генерирует две функции для каждого столбца, которые должны допускать DBNULL. Они предназначены для использования при работе с NULL, но это неуклюжие решения Microsoft. Что происходит за кулисами, так это то, что адаптер таблицы выводит столбец DefaultValue вместо NULL из функции Get. Я называю это "имитированный NULL" или "поддельный NULL".

Функция IsParentIDNull() фактически проверит, содержит ли строка этот "поддельный NULL", например. столбец DefaultValue, и когда это произойдет, я вставляю соответствующий DBNull с помощью функции SetParentIDNull().

Это решение работает для меня, но не очень элегантно и не очень эффективно, но я надеюсь, что это может помочь кому-то другому.

Ответ 6

Я не уверен, почему var x = !IsMyFieldNull() ? MyField : null (или подобное) является такой головной болью.

Я полагаю, вы могли бы написать оболочку вокруг SqlDataReader, чтобы каким-то образом уловить эти нулевые значения, когда вы читаете данные в своем DataTable, или вы можете записать эквивалент .TryParse() для своих запросов: что-то приятное и инкапсулированное, например:

var x = myDataTable.TryParse(myField);

где .TryParse - это метод расширения, выглядящий примерно так:

public static TryParse(DataRow myField)
{
    if(!myField == DbNull) //Or similar
       return myField.Value;
}

Это, как вы можете видеть, в основном псевдокод грубый, но вы получаете идею. Напишите свой код один раз, затем назовите его как метод расширения.

Ответ 7

В .net 3.0 были введены типы Nullable, которые могут использоваться с наборами данных. Вы объявляете nullable int как это int? myNullableInt = null Вот ссылка на статью MSDN: Nullable Types С#

Лично я сначала избегаю нулей в базах данных (если вам это нравится). NULL действительно существует, чтобы обеспечить статус "Undefined" или "Неизвестный". Редко эта проблема возникает, например, для строкового поля, содержащего фамилию, часто устанавливается значение "nullable", тогда как значение "было бы намного лучшим вариантом. Помещение нулей в базы данных делает вещи излишне жесткими Нулевые значения в Базах данных, кроме того, он распространяет нули в код, и вам приходится работать, чтобы избежать исключений с нулевой ссылкой.

К сожалению, в Интернете много вредоносных вещей, связанных с БД (например, чрезмерное использование null как OK). Эти точки зрения обычно принадлежат людям, которые действительно не понимают теорию, лежащую в их основе, а другой классический пример - это БД без отношений "потому что это более гибко/быстрее обрабатывать их в коде". Это означает, что разработчик должен перезаписать существующие функциональные возможности [уровня базы данных], которые неизбежно работают с гарантией базы данных и с большей надежностью. Я говорю о неизбежности, поскольку, конечно же, разработчик, занимающийся переписыванием, переустанавливает материал, который Oracle/Microsoft/Тот, у кого были большие команды, которые тратят много времени на оптимизацию и т.д. Но каждый раз часто вы видите, что кто-то защищает это как дизайн. Этот парень действительно понимает базы данных, DBDebunkings он потратил много времени, пытаясь развенчать много бессмысленных решений, которые берут реляционные базы данных далеко от их теоретических корней.