Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: ".Net";
Текущий архив: 2009.12.13;
Скачать: [xml.tar.bz2];

Вниз

ADO.NET: можно ли преобразовать DBNull ?   Найти похожие ветки 

 
Bronco ©   (2005-08-16 16:50) [0]

Ситуация следующая:
Есть некий класс с определенным набором полей.
Каждому полю присваиваю значения из DataTable
например:
DateOpen = Convert.ToDateTime(DT1.Rows[0]["DateOpen"]);
где DateOpen - поле класса типа DateTime.
Все хорошо до тех пор, пока в DataTable не натыкаюсь на пустое значение поля. Тут возникает exception, говорящий о том, что невозможно преобразовать DBNull в DateTime.
Конечно есть вариант каждый раз проверять поле на наличие в нем пустого значения, напр. так:
if (Convert.IsDBNull(DT1.Rows[0]["DateOpen"]))
DateOpen = Convert.ToDateTime(null);
else
DateOpen = Convert.ToDateTime(DT1.Rows[0]["DateOpen"]);

но как-то громоздко это, да и полей много, придется для каждого писать такую конструкцию.
Может есть более простые способы преобразования DBNull в нужный тип?
Спасибо заранее.


 
DiamondShark ©   (2005-08-16 17:41) [1]


> Может есть более простые способы преобразования DBNull в
> нужный тип?

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


> Конечно есть вариант каждый раз проверять поле на наличие
> в нем пустого значения, напр. так:
> if (Convert.IsDBNull(DT1.Rows[0]["DateOpen"]))
> DateOpen = Convert.ToDateTime(null);
> else
> DateOpen = Convert.ToDateTime(DT1.Rows[0]["DateOpen"]);

Плохой вариант.
Convert.ToXXX с аргументом null возвращает для value-типов заполненное нулями значение.
И если дата 01-01-0001 (а это и есть "нулевая" дата) хотя и вполне валидное, но несколько экзотическое значение, то, скажем, нулевой Int32 или Double -- вообще ничем не примечательны.

Никакого универсального (т.е. не зависящего от логики конкретного приложения) преобразования DBNull -> value-type нет и быть не может.
По определению.


 
Bronco ©   (2005-08-16 17:56) [2]


> DiamondShark ©   (16.08.05 17:41) [1]


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

Расскажу. См. класс TField в Delphi. Он почему-то "знает" как преобразовывать пустое (null) значение.


> Плохой вариант.

не понял, что в этом плохого? Ну нулевая дата, и что? По условию дата вполне может отсутствовать. А как по-другому инициализировать поле класса пустым значением?


 
Bronco ©   (2005-08-16 18:04) [3]

Дополнение: насчет TField могу ошибаться.
Но либо он, либо движок соответствующей БД занимается этим преобразованием. И точно знает во что нужно преобразовать null в каждом конкретном случае.


 
DiamondShark ©   (2005-08-16 18:49) [4]


> Расскажу. См. класс TField в Delphi. Он почему-то "знает"
> как преобразовывать пустое (null) значение.

Фиги разные. Класс TField ничего не преобразует. Он имеет свойство Value типа Variant (для которого значение NULL входит в множество значений) и свойство IsNull.
А методы доступа свойств AsXXX -- заглушки с исключениями.
Преобразования вводят классы-наследники.


> не понял, что в этом плохого? Ну нулевая дата, и что?

А то, что нулевая дата и null -- это разные значения.
А с целыми ты что будешь делать? Нулём заменять? Так ноль -- значение не лучше и не хуже любого другого.


> Но либо он, либо движок соответствующей БД занимается этим
> преобразованием. И точно знает во что нужно преобразовать
> null в каждом конкретном случае.

Ничем подобным никакой движок не занимается. Null -- он по-жизни Null.

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


 
Канадец   (2005-08-16 22:35) [5]

>Bronco ©
Эта проблема не одному тебе спать не даёт. Никаких преобразований структурных типов в null, естественно, нет и как здесь правильно заметили, быть не может. Microsoft обещает исправиться в .net framework 2.0 введением  Nullable Types.


 
Bronco ©   (2005-08-17 11:05) [6]


> DiamondShark ©   (16.08.05 18:49) [4]

Демагогия чистой воды.
А на вопрос ты все-таки мне ответь: чем инициализировать дату (поле класса), если она в базе null ? (только не надо говорить "чем угодно")

Я все-таки повторюсь, что в TField(его наследниках) эта проблема была решена вполне приемлемо. В .Net судя по всему - нет. (Основной мой вопрос закрыт)
Ты с пеной у рта можешь доказывать что "null это null и каждый для себя должен сам решать, во что его преобразовывать", а мое мнение, что это есть недоработка Microsoft, поскольку существует очевидное решение этой проблемы, которое годами использовалось (кстати тем же Microsoft-ом)


> Канадец   (16.08.05 22:35) [5]

Спасибо, я уже так и понял. Хотелось бы верить, что исправятся.


 
Игорь Шевченко ©   (2005-08-17 11:52) [7]

Bronco ©   (17.08.05 11:05) [6]


> Я все-таки повторюсь, что в TField(его наследниках) эта
> проблема была решена вполне приемлемо.


И как она решена ?


 
DiamondShark ©   (2005-08-17 12:33) [8]


> Демагогия чистой воды.

Убей себя об стену.


> А на вопрос ты все-таки мне ответь: чем инициализировать
> дату (поле класса), если она в базе null ? (только не надо
> говорить "чем угодно")

Ничем. Чем бы ты не инициализировал, всё равно это будет валидное значение типа. И, следовательно, встаёт проблема отличения одного валидного значения, которое подставлено вместо null, от другого такого же значения, но которое не подставлено вместо null.
В одних случаях можно выделить из области значений такие, которые заведомо не используются в задаче, и использовать их. В других случаях нельзя.
Но абсолютно приемлемого решения нет, кроме как расширить область значений, например, дополнив флагом IsNull.


> Я все-таки повторюсь, что в TField(его наследниках) эта
> проблема была решена вполне приемлемо.

Ты туп. TField -- это структура, содержащая атомарное значение плюс флаг IsNull. А ты хочешь обойтись только атомарным значением.


> В .Net судя по всему - нет.

Используй вместо value-типов object.
Тогда у тебя переменные будут содержать либо boxed-значение, либо null.


> поскольку существует очевидное решение этой проблемы, которое
> годами использовалось (кстати тем же Microsoft-ом)

(*вкрадчивым голосом*)И какое же?


 
Bronco ©   (2005-08-17 13:53) [9]


> Игорь Шевченко ©   (17.08.05 11:52) [7]

ну например, взгляни на код методов
TStringField.GetAsString
TIntegerField.GetAsInteger

Если в наборе данных обнаруживается null (GetData вернула False), то возвращается наиболее близкое по смыслу значение для каждого из типов.
Для string - пустая строка. Для integer - 0 и т.д. Чем не решение?
Я конечно не хочу сказать, что такой подход претендует на истину, но для меня это было гораздо удобнее, чем самому отлавливать null-ы и преобразовывать их во что бы то ни было.


> DiamondShark ©   (17.08.05 12:33) [8]

Побереги нервы, дружище.


 
Суслик ©   (2005-08-17 13:56) [10]


>  [9] Bronco ©   (17.08.05 13:53)


> > DiamondShark ©   (17.08.05 12:33) [8]
>
> Побереги нервы, дружище.


А ты послушай, что он говорит :)
Особенно про boxing


 
Bronco ©   (2005-08-17 14:03) [11]

Удалено модератором


 
Суслик ©   (2005-08-17 14:13) [12]


> [11] Bronco ©   (17.08.05 14:03)

Я прав, а ты нет :)
Он тебе очень дельно объяснил. И теорию реализации null, и практику (object + boxing).
Читай.


 
Игорь Шевченко ©   (2005-08-17 14:35) [13]

Bronco ©   (17.08.05 13:53) [9]


> ну например, взгляни на код методов
> TStringField.GetAsString
> TIntegerField.GetAsInteger


Коран запрещает сделать подобную функциональность в своей программе ?


> Если в наборе данных обнаруживается null (GetData вернула
> False), то возвращается наиболее близкое по смыслу значение
> для каждого из типов.


Степень близости по смыслу можно узнать ? :)


 
Bronco ©   (2005-08-17 14:43) [14]


> Суслик ©   (17.08.05 14:13) [12]

Прав тот у кого больше прав. А у нас с тобой их одинаково. Я неправ? :-)
--
Вобщем, с таким подходом пока тоже есть определенные непонятки.
1) Слишком критична скорость работы программы. Постоянные обращения к полям класса. Как скажется время на распаковку объектов на скорости работы программы... пока неясно. Буду проверять.
2) Опять же, при обращении к объекту, дабы получить значение мне придется сначала проверять его на null, т.е. лишнего if-a не избежать. Либо писать собственный метод. Или я чего не понимаю?


 
Bronco ©   (2005-08-17 14:50) [15]


> Игорь Шевченко ©   (17.08.05 14:35) [13]


> Коран запрещает сделать подобную функциональность в своей
> программе ?

Нет конечно :-)


> Степень близости по смыслу можно узнать ? :)

Ну хорошо. Придрался-таки к словам :-) Термин "степень близости" видимо тут не подходит. Просто некие дяди постановили null в числовом поле преобразовывать в 0. Null в символьном поле преобразовывать в "". И мне удобно и им, видимо, проблем меньше :-)


 
k2 ©   (2005-08-17 14:57) [16]

а в символьном итак null преобразуется в "",так што вам делов-то осталось всего ничего


 
DiamondShark ©   (2005-08-17 14:59) [17]

А вообще, как мне кажецца, вы фигнёй страдаете.

Я вот в VS создал DataSet, она мне радостно сгенерировала классы-обертки для таблиц и строк.

Смотрю:

public long Field1 {
   get {
       try {
           return ((long)(this[this.tableTable1.Field1Column]));
           }
       catch (InvalidCastException e) {
           throw new StrongTypingException("Cannot get value because it is DBNull.", e);
       }
   }
   set {
        this[this.tableTable1.Field1Column] = value;
       }
   }

Это, если кто не понял, кусок из автогенерированного наследника DataRow

Теперь открываем схему данных, выделяем поле, и в свойство NullValue пишем, например, 123.
Смотрим код:


public long Field1 {
   get {
       if (this.IsField1Null()) {
           return 123;
       }
       else {
           return ((long)(this[this.tableTable1.Field1Column]));
       }
   }
   set {
       this[this.tableTable.Field1Column] = value;
   }
}


Короче, не надо про "недоработки Microsoft"...


 
DiamondShark ©   (2005-08-17 15:04) [18]

ЗЫ
Есть ли такая тулзовина в Дельфи -- не знаю, бо пользуюсь вражеским продуктом.


 
Bronco ©   (2005-08-17 15:13) [19]


> DiamondShark ©   (17.08.05 14:59) [17]

Дык я тоже про VS говорю. О Дельфи пока речи нет.
Ну, в твоем коде, как я понял, используется типизированный DataSet, у меня немного другой случай. Есть DataTable без всяких DataSet-ов. И каждый раз в нем может оказаться неизвестно какая структура данных. Под каждый случай создавать типизированный набор данных... хотя может и стоит поменять подход.


 
DiamondShark ©   (2005-08-17 15:39) [20]

Да, типизированный.
А как, извиняюсь, "некий класс с определенным набором полей" может взаимодействовать с "неизвестно какой структурой данных"?


 
Bronco ©   (2005-08-17 16:12) [21]


> DiamondShark ©   (17.08.05 15:39) [20]

Классов несколько, каждый предназначен для своих целей.
Все классы имеют потребность периодически получать некую инфу из базы. Т.е. каждый класс дает свой sql запрос. При этом, в рантайме создается DataTable и возвращается как результат.


 
Суслик ©   (2005-08-18 11:27) [22]


> [21] Bronco ©   (17.08.05 16:12)


Если так, то пиши предка - суперкласс, который:
1. Содержит метаинформацию о полях.
2. Умеет читать таблицу.

В общем, примерно как в дельфи сделано.


 
Bronco ©   (2005-08-18 12:18) [23]


> Суслик ©   (18.08.05 11:27) [22]

По хорошему, наверное, надо было так и сделать.
Но я пока решил проблему с DBNull другим путем.
Отказался от использования класса Convert, и написал собственный (DBConvert), методы которого включают проверку на DBNull. По-моему так "дешевле".


 
Суслик ©   (2005-08-18 12:21) [24]


> По-моему так "дешевле".

Это тебе решать.

Решение о создании суперкласса сильно зависит от решаемой задачи и от ПОВТОРЯЕМОСТИ решения данной задачи в будущем.

Меня раньше хлебом не корми, а дай написать инструментарий. Сейчас я долго буду думать и анализировать целесообразность данного действа.

Так, что, скорее всего, так именно "дешевле".


 
Polevi ©   (2005-08-18 12:38) [25]

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



Страницы: 1 вся ветка

Форум: ".Net";
Текущий архив: 2009.12.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.017 c
2-1256109863
RWolf
2009-10-21 11:24
2009.12.13
AnsiExtractQuotedStr(PChar(str), ...)


2-1256277237
kyn66
2009-10-23 09:53
2009.12.13
Подсчет среднего значения с нулевыми числами


15-1255747691
Ruzzz
2009-10-17 06:48
2009.12.13
Красивое поведение при сворачивании в трей


15-1255523606
s_t_d
2009-10-14 16:33
2009.12.13
Книга, где есть основы работы с IDE MS Visual Studio 2008


15-1255375820
Unknown user
2009-10-12 23:30
2009.12.13
Запутался





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский