Как зайти в Даркнет?!
25th January, 01:11
5
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Как лучше всего бороться с DBNull-Ми
У меня часто возникают проблемы, связанные с DataRows возвращением из SqlDataAdapters . Когда я пытаюсь заполнить объект с помощью такого кода:
DataRow row = ds.Tables[0].Rows[0];
string value = (string)row;
Как лучше всего справиться с DBNull's в такой ситуации?
Nullable типы хороши, но только для типов, которые изначально не являются nullable.
Чтобы создать тип "nullable", добавьте к нему вопросительный знак, например:
int? value = 5;
Я бы также рекомендовал использовать ключевое слово "as"вместо приведения. Вы можете использовать ключевое слово "as" только для nullable типов, поэтому убедитесь, что вы создаете вещи, которые уже являются nullable (например, строки) или используете nullable типы, как указано выше. Рассуждение для этого
- Если тип является nullable, ключевое слово "
as" возвращаетnull, если значение равноDBNull. - Это ever-so-slightly быстрее, чем кастинг , хотя только в некоторых случаях . Это само по себе никогда не является достаточно хорошей причиной для использования
as, но в сочетании с приведенной выше причиной это полезно.
Я бы рекомендовал сделать что-то вроде этого
DataRow row = ds.Tables[0].Rows[0];
string value = row as string;
В приведенном выше случае, если row возвращается как DBNull, то value станет null вместо того, чтобы создавать исключение. Имейте в виду, что если ваш запрос DB изменяет возвращаемые столбцы/типы, то использование as приведет к молчаливому сбою кода и сделает значения простыми null вместо того, чтобы создавать соответствующее исключение при возврате неверных данных, поэтому рекомендуется использовать тесты для проверки ваших запросов другими способами, чтобы обеспечить целостность данных по мере развития вашей кодовой базы.
Если вы не используете nullable типы, лучше всего проверить, является ли значение столбца DBNull. Если это DBNull, то установите ссылку на то, что вы используете для null/пустой для соответствующего типа данных.
DataRow row = ds.Tables[0].Rows[0];
string value;
if (row["fooColumn"] == DBNull.Value)
{
value = string.Empty;
}
else
{
value = Convert.ToString(row["fooColumn"]);
}
Как сказал Ману, вы можете создать класс convert с перегруженным методом convert для каждого типа, поэтому вам не нужно перчить свой код блоками if/else.
Однако я подчеркну, что nullable types-это лучший маршрут, если вы можете их использовать. Рассуждение состоит в том, что с ненулевыми типами вам придется прибегнуть к "magic numbers", чтобы представить null. Например, если вы сопоставляете столбец с переменной int, как вы собираетесь представить DBNull? Часто вы не можете использовать 0, потому что 0 имеет допустимое значение в большинстве программ. Часто я вижу, как люди сопоставляют DBNull с int.MinValue,но это тоже может быть проблематично. Мой лучший совет таков:
- Для столбцов, которые могут быть null в базе данных, используйте типы nullable.
- Для столбцов, которые не могут быть null в базе данных, используйте обычные типы.
Для решения этой проблемы были созданы типы, допускающие обнуление. Тем не менее, если вы находитесь на более старой версии фреймворка или работаете на кого-то, кто не использует grok nullable types, пример кода сделает свое дело.
Я всегда находил его ясным, кратким и без проблем использующим версию проверки If/Else, только с тернарным оператором. Сохраняет все в одной строке, включая присвоение значения по умолчанию, если столбец имеет значение null.
Итак, предположим, что nullable Int32 столбец с именем "MyCol", где мы хотим вернуть -99, если столбец null, но возвращаем целое значение, если столбец не null:
return row["MyCol"] == DBNull.Value ? -99 : Convert.ToInt32(Row["MyCol"]);
Это тот же метод, что и у победителя If / Else выше , но я обнаружил, что если Вы читаете несколько столбцов из datareader, это настоящий бонус, когда все строки для чтения столбцов расположены друг под другом, выстроившись в ряд, так как легче обнаружить ошибки:
Object.ID = DataReader["ID"] == DBNull.Value ? -99 : Convert.ToInt32(DataReader["ID"]);
Object.Name = DataReader["Name"] == DBNull.Value ? "None" : Convert.ToString(DataReader["Name"]);
Object.Price = DataReader["Price"] == DBNull.Value ? 0.0 : Convert.ToFloat(DataReader["Price"]);
Если у вас есть контроль над запросом, который возвращает результаты, вы можете использовать ISNULL() для возврата значений, отличных от null, например:
SELECT
ISNULL(name,'') AS name
,ISNULL(age, 0) AS age
FROM
names
Если ваша ситуация допускает, что эти магические значения заменяют NULL, такой подход может устранить проблему во всем вашем приложении, не загромождая ваш код.
DBNull орудия труда .ToString() как и все остальное. Не нужно ничего делать. Вместо жесткого броска вызовите объект .ToString() метод.
DataRow row = ds.Tables[0].Rows[0];
string value;
if (row["fooColumn"] == DBNull.Value)
{
value = string.Empty;
}
else
{
value = Convert.ToString(row["fooColumn"]);
}
это становится:
DataRow row = ds.Tables[0].Rows[0];
string value = row.ToString()
DBNull.ToString() возвращает string.Empty
Я бы предположил, что это лучшая практика, которую вы ищете
Стоит отметить, что DBNull.Value.ToString() равно String.Empty
Вы можете использовать это в своих интересах:
DataRow row = ds.Tables[0].Rows[0];
string value = row["name"].ToString();
Однако это работает только для строк, для всего остального я бы использовал путь linq или метод расширения. Для себя я написал небольшой метод расширения, который проверяет DBNull и даже делает кастинг через Convert.ChangeType(...)
int value = row.GetValueOrDefault<int>("count");
int value = row.GetValueOrDefault<int>("count", 15);
Часто при работе с DataTables вам приходится иметь дело с такими случаями, когда поле строки может быть либо null, либо DBNull, обычно я имею дело с этим так:
string myValue = (myDataTable.Rows[i]["MyDbNullableField"] as string) ?? string.Empty;
Оператор 'as' возвращает null для недопустимых приведений, например DBNull в строку, и '??' возвращает термин справа от выражения, если первым является null.
Брэд Абрамс опубликовал что-то связанное всего пару дней назад http://blogs.msdn.com/brada/archive/2009/02/09/framework-design-guidelines-system-dbnull.aspx
В итоге "AVOID использует System.DBNull. Вместо этого предпочтите Nullable."
А вот мои два цента (непроверенного кода :) )
// Or if (row["fooColumn"] == DBNull.Value)
if (row.IsNull["fooColumn"])
{
// use a null for strings and a Nullable for value types
// if it is a value type and null is invalid throw a
// InvalidOperationException here with some descriptive text.
// or dont check for null at all and let the cast exception below bubble
value = null;
}
else
{
// do a direct cast here. dont use "as", "convert", "parse" or "tostring"
// as all of these will swallow the case where is the incorect type.
// (Unless it is a string in the DB and really do want to convert it)
value = (string)row["fooColumn"];
}
И еще один вопрос... Есть ли причина, по которой вы не используете ORM?
Обычно я пишу свой собственный класс ConvertDBNull, который обертывает встроенный класс Convert. Если значение равно DBNull, то он вернет null, если это ссылочный тип, или значение по умолчанию, если это тип значения.
Пример:
- ConvertDBNull.ToInt64(object obj) возвращает Convert.ToInt64(obj) , если obj не является DBNull, и в этом случае он возвращает 0.
Если вы заинтересованы в получении DBNull при ожидании строк, один из вариантов заключается в преобразовании всех значений DBNull в DataTable в пустую строку.
Это довольно просто сделать, но это добавит некоторые накладные расходы, особенно если вы имеете дело с большими DataTables. Проверьте эту ссылку , которая показывает, как это сделать, если вы заинтересованы