Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ADO.NET: можно ли преобразовать DBNull ? [C#, WinXP]


Страницы:   1 2

Bronco ©   (2005-08-16 16:50:00) 

Ситуация следующая:
Есть некий класс с определенным набором полей.
Каждому полю присваиваю значения из 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 в нужный тип?
Спасибо заранее.


Polevi   (2005-08-18 12:38:00) [1]

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


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


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

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

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

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

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


Bronco   (2005-08-18 12:18:00) [3]


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

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


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


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


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

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


Bronco   (2005-08-17 16:12:00) [5]


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

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


DiamondShark   (2005-08-17 15:39:00) [6]

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


Bronco   (2005-08-17 15:13:00) [7]


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

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


DiamondShark   (2005-08-17 15:04:00) [8]

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


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

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

Я вот в 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"...


k2   (2005-08-17 14:57:00) [10]

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


Bronco   (2005-08-17 14:50:00) [11]


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


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

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


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

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


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


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

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


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

Bronco ©   (17.08.05 13:53) [9]


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


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


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


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


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


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

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


Bronco   (2005-08-17 14:03:00) [15]

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


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


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


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


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


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


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

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

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


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

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


DiamondShark   (2005-08-17 12:33:00) [18]


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

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


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

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


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

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


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

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


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

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


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

Bronco ©   (17.08.05 11:05) [6]


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


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


Bronco   (2005-08-17 11:05:00) [20]


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

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

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


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

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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо