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

Вниз

IBDataSet, Master-Detail и Insert   Найти похожие ветки 

 
grav   (2008-05-20 09:45) [0]

Есть три связанных IBDataSet.
MasterDS-DetailDS1-DetailDS2. Соответственно Предприятие-Здания-данные по зданию. Предприятий много, у каждого прежприятия зданий много, у каждого здания одна запись с данными (площадь, стоимость и т.д.).
Список предприятий не меняется. Здания могут добавляться, редактироваться и удаляться. Данные по зданию могут редактироваться, удаляться вместе со зданием и добавляться вместе со зданием.
Встака записей в таблицу здания проходит без проблем. Вставка в тблицу с данными по зданию проходит без ошибок, но в таблицу не попадают. Почему? Как отследить что не так, если никаких ошибок не выводится?


 
Anatoly Podgoretsky ©   (2008-05-20 09:53) [1]

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


 
Sergey13 ©   (2008-05-20 09:57) [2]

> [0] grav   (20.05.08 09:45)
> Как отследить что не так, если никаких ошибок не выводится?

Как обычно - ковыряться в коде и в пропертях компонентов. Как еще то?


 
grav   (2008-05-20 10:02) [3]


> Anatoly Podgoretsky ©   (20.05.08 09:53) [1]

Дело в том, что база сложнее. У каждого здания есть еще объекты.
Получается так: Предприятие-Здания-Объекты. Но...
У Предприятия, здания и объекта есть свои данные (площадь, стоимость и т.д.). Вот эти данные я и вынес в отдельную таблицу. Предполагается, что предприятий будет около 6 тыс., зданий от нескольких единиц до нескольких сот, объектов тысячи, таблица с данными будет содержать под миллион записей.


 
Sergey13 ©   (2008-05-20 10:08) [4]

> [3] grav   (20.05.08 10:02)

У одного здания или объекта может быть НЕСКОЛЬКО площадей и/или стоимостей?


 
grav   (2008-05-20 10:09) [5]


> Sergey13 ©   (20.05.08 09:57) [2]

Делаю
DetailDS2.Inset;
DetailDS2.FieldByName(ID_ORG).AsInteger:=DetailDS1.FieldByName(ID_ORG).AsInteger ;
DetailDS2.FieldByName(ID_Build).AsInteger:=DetailDS1.FieldByName(ID).AsInteger;
DetailDS2.FieldByName(ID_OBJ).AsInteger:=0;
DetailDS2.Post;

Эти три поля образуют ключ и являются единственными полями, которые не могут быть NULL.
Проверяю DetailDS2.UpdatesPending , изменения есть. Делаю
DetailDS2.ApplyUpdates;
MainForm.StartTr.Commit;
Все проходит без ошибок. Данные в таблице не появляются.

Тоже самое, если делать DetailDS2.Edit;


 
grav   (2008-05-20 10:14) [6]


> Sergey13 ©   (20.05.08 10:08) [4]

Нет, запись по каждому зданию и объекту в таблице с данными одна. Выделил эти данные в отдельную таблицу только из-за того, что поля в таблицах одинаковы (правда не все поля пересекаются, т.е. некоторые поля уникальны для объекта или здания).


 
Sergey13 ©   (2008-05-20 10:17) [7]

> [5] grav   (20.05.08 10:09)
> Эти три поля образуют ключ

Какой ключ? Первичный? А почему не просто ID, как в других (насколько я понял) таблицах.?
Что есть такое ID_OBJ?


 
grav   (2008-05-20 10:17) [8]

Еще вот что.
Все вышеописанное, т.е. Inset и Edit для DetailDS1 работает без проблем.
Есть еще одна свзяка DetailDS1-DetailDS3 (здания-0бъекты), также не работает вставка и редактирование.


 
grav   (2008-05-20 10:17) [9]

Еще вот что.
Все вышеописанное, т.е. Inset и Edit для DetailDS1 работает без проблем.
Есть еще одна свзяка DetailDS1-DetailDS3 (здания-0бъекты), также не работает вставка и редактирование.


 
Sergey13 ©   (2008-05-20 10:21) [10]

> [6] grav   (20.05.08 10:14)

Ты все таки удивительно хреново описываешь свою задачу.
Давай просто структуру таблиц - без своих коментариев (пока не попросят 8-)

Здания и объекты - это в одной таблице?

> что поля в таблицах одинаковы

В каких таблицах?


 
Anatoly Podgoretsky ©   (2008-05-20 10:24) [11]

> grav  (20.05.2008 10:02:03)  [3]

Может ты не договариваешь, говоришь о один к одному, а на самом деле один ко многим.
Реализовывать связь один к одному имеет смысл только по архитектурным ограничениями СУБД


 
Anatoly Podgoretsky ©   (2008-05-20 10:25) [12]

> Sergey13  (20.05.2008 10:08:04)  [4]

Может быть, площадь может измениться, а стоимость и тем более, но это называется история и там как правило еще и связи многие ко многим.


 
ЮЮ ©   (2008-05-20 10:26) [13]

> Выделил эти данные в отдельную таблицу только из-за того,
> что поля в таблицах одинаковы


Главная ошибка первых лет проектирования баз жанных :)

Похожесть атрибутов разных сущностей — не повод порождать синтетическую сущность, ИМХО.

Атрибуты зданий — в таблицу зданий, атрибуты объектов — в таблицу объектов


> зданий от нескольких единиц до нескольких сот, объектов
> тысячи, таблица с данными будет содержать под миллион записей.

Странная арифметика.

данные = здания + объекты = тысячи. Откуда миллионы?


 
grav   (2008-05-20 10:34) [14]


> Sergey13 ©   (20.05.08 10:21) [10]

Имеется три таблицы ORGAN, BUILDING и DATA.
В таблице ORGAN есть ключ с именем ID и поля с кодами организации из справочников.
В таблице BUILDING есть ключ ID и поле ID_ORG (для связи  с таблицей ORGAN).
В таблице DATA есть тройной ключ: ID_ORG, ID_BUILD, ID_OBJ, уникальный, данные поля не могут быть null.
Если в таблице DATA: ID_ORG<>0, а ID_BUILD=ID_OBJ=0 - это означает, что данная запись принадлежит предприятию
Если ID_ORG<>0 и ID_BUILD<>0, а ID_OBJ=0 - запись принадлежит зданию
Если ID_ORG<>0 и ID_BUILD<>0 и ID_OBJ<>0 - запись принадлежит объекту (ID_OBJ из генератора).


 
grav   (2008-05-20 10:40) [15]


> Anatoly Podgoretsky ©   (20.05.08 10:25) [12]

История не нужна, это разовое обследование инфраструктуры.


> ЮЮ ©   (20.05.08 10:26) [13]

Я не писал миллионы, я писал под миллион записей. В каждом предприятии может сотня зданий, в каждом здании сотня объектов. Итого у предприятия м.б. тысяча объектов. 6000 предприятий на 1000 объектов = 6 миллионов. Но я думаю будет около миллиона.


 
ЮЮ ©   (2008-05-20 10:43) [16]

> Если ID_ORG<>0 и ID_BUILD<>0, а ID_OBJ=0 &#151; запись принадлежит

Не смущает, что BUILDING с таким ID может запросто принадлежать другой ORGAN, не той что в ID_ORG?
ID_ORG в таблице здесь соверщенно лишний!!!


 
Sergey13 ©   (2008-05-20 10:46) [17]

> [12] Anatoly Podgoretsky ©   (20.05.08 10:25)
> Может быть, площадь может измениться

У него похоже все что угодно может быть. Второй топик клещами приходится по крупицам информацию выдирать. Партизан какой-то.


 
ЮЮ ©   (2008-05-20 10:48) [18]

> (правда не все поля пересекаются, т.е. некоторые поля уникальны
> для объекта или здания).


Даже не экономишь на месте :) Тогда в чем причина?
Настаиваю на ORGANS, BUILDINGS и OBJECTS.

P.S. Имя таблицы организаций диссонируют с именами других таблиц, не замечаешь?


 
Sergey13 ©   (2008-05-20 10:53) [19]

> [14] grav   (20.05.08 10:34)

А может быть здание без объектов?


 
grav   (2008-05-20 10:57) [20]


> ЮЮ ©   (20.05.08 10:43) [16]

Да, красноречив это не про меня :)
Три поля ID_ORG, ID_BUILD и ID_OBJ образуют уникальный ключ. Т.е. знацения 5,0,0 уникально и данные этой записи будут принадлежать организации. Т.е. когда я сделаю select * from DATA where ID_ORG=5 and ID_BUILD=0 and ID_OBJ=0 отберется одна запись.


 
grav   (2008-05-20 10:58) [21]


> Sergey13 ©   (20.05.08 10:53) [19]

Нет. Что то в нем есть, иначе зачем здание?


 
grav   (2008-05-20 11:02) [22]

Вообщем то данные в базу уже заносятся.
Я пытаюсь дописать изменение данных. Мне без проблем это сделать с помощью обычных IBQuery или IBSQL. Но вот захотелось чрез DBGrid"ы и мастер детайл.


 
ЮЮ ©   (2008-05-20 11:08) [23]

> Если в таблице DATA: ID_ORG<>0, а ID_BUILD=ID_OBJ=0 &#151; это
> означает, что данная запись принадлежит предприятию


Ты туда ещё и характеристики предприятия примешал :)


> Да, красноречив это не про меня :)

Я не о том.
Пусть имеем
 ORGAN      BUILDING
 ID         ID  ID_ORG          
 1          1    1
 2          2    2


Если не делать особых телодвищений по обеспецению правильности данных, то в  
DATA запросто может оказаться
ID_ORG ID_BUILD ID_OBJ  
  1       2      222


 
Sergey13 ©   (2008-05-20 11:14) [24]

> [21] grav   (20.05.08 10:58)

Тогда однозначно

> [18] ЮЮ ©   (20.05.08 10:48)
> Настаиваю на ORGANS, BUILDINGS и OBJECTS.


 
ЮЮ ©   (2008-05-20 11:27) [25]

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

организации
SELECT Id FROM Organs
 инфа об организации
 SELECT * FROM DATA WHERE (ID_ORG = :Id) and (ID_BUILD = 0) AND (ID_OBJ = 0)  

 здания организации
 SELKCT Id,  ID_ORG  FROM BUILDING WHERE (ID_ORG = :Id)
   
   инфа о зданиях
   SELECT * FROM DATA WHERE (ID_ORG = :Id_Orп) and (ID_BUILD = :Id) AND (ID_OBJ = 0)  

   объекты хдания
   SELECT * FROM DATA WHERE (ID_ORG = :Id_Orп) and (ID_BUILD = :Id_Bild) AND (ID_OBJ <> 0)
 

З.Ы. detail-запросы сдвинуты относительно master


 
grav   (2008-05-20 11:29) [26]


> ЮЮ ©   (20.05.08 11:08) [23]

Если датасеты свзяаны между собой то такого быть не может вроде бы. Т.к. Если пользователь выбрал предприятие в гриде, то во втором гриде отображаются только здания принадлежащие данному предприятию. Тогда при добавлении в таблицу данных Из DetailDS2 возьмется ID_ORG=1 ID_BUILD=1, других данных в датасете не будет просто.


 
ЮЮ ©   (2008-05-20 11:33) [27]

> Т.к. Если пользователь выбрал предприятие в гриде, то во
> втором гриде отображаются только здания принадлежащие данному
> предприятию.

Гридов у тебя еще нет, а IBExpert у кого-нибудь найдется :)


 
ЮЮ ©   (2008-05-20 11:39) [28]

> Делаю
> DetailDS2.Inset;
> DetailDS2.FieldByName(ID_ORG).AsInteger:=DetailDS1.FieldByName(ID_ORG)
> .AsInteger ;
> DetailDS2.FieldByName(ID_Build).AsInteger:=DetailDS1.FieldByName(ID)
> .AsInteger;
> DetailDS2.FieldByName(ID_OBJ).AsInteger:=0;
> DetailDS2.Post;


в каком методе?
А где пользовательские данные, что он колотил в гриде?

В этом коде втавка пустой строки, соответсиыующкй новой строке в BUILDING.
А как пользователь добавит запись в таблицу BUILDING, если та нечего отобрвжать в гриде?


 
grav   (2008-05-20 11:40) [29]

Как нет гридов. Есть гриды, отображение работает, редактирование данных по организации работает, т.к. IBTable там вкачестве detail.
Редактирование, вставка и удаление в(из) таблицу Building работает.
Не работает вставка и редактирование в DetailDS3, т.е. в третий датасет в связке.


 
grav   (2008-05-20 11:46) [30]

> ЮЮ ©   (20.05.08 11:39) [28]

Пользовательские данные в данном случае не в гриде, а в DBEdit"ах, ибо зачем под одну строку отводить грид (хотя первоначально так у меня и было). Передаются запросом из InsertSQL


> В этом коде втавка пустой строки, соответсиыующкй новой
> строке в BUILDING.

Да, так и есть.

DetailDS1.Insert;
DetailDS1.FieldByName("ID_ORG").AsInteger:=OrganDS.FieldByName("ID").AsInteger;
DetailDS2.Insert;
DetailDS2.FieldByName("ID_ORG").AsInteger:=BuildDS.FieldByName("ID_ORG").AsInteg er;
DataBDS.FieldByName("ID_BUILD").AsInteger:=BuildDS.FieldByName("ID").AsInteger;
DetailDS2.FieldByName("ID_OBJ").AsInteger:=0;
SaveBtn.Enabled:=True;


 
ЮЮ ©   (2008-05-20 11:47) [31]

> т.к. IBTable там вкачестве detail.

Остется тихо удалиться :)
Хотя бы дельфийский help по мастер-детайл почитал бы.


> Тогда при добавлении в таблицу данных Из DetailDS2 возьмется
> ID_ORG=1 ID_BUILD=1, других данных в датасете не будет просто.

У тебя же  датасет &#151; IBTable. Там всё должно быть :)


> Редактирование, вставка и удаление в(из) таблицу Building
> работает.

Интересно, что можно вставить в гриде для таблицы BUILDING(ID, ID_ORG)? Или там ещё поля есть? Почему они тогда не в DATA?


 
ЮЮ ©   (2008-05-20 11:54) [32]

> DetailDS1.Insert;
> DetailDS1.FieldByName("ID_ORG").AsInteger:=OrganDS.FieldByName("ID")
> .AsInteger;
> DetailDS2.Insert;
> DetailDS2.FieldByName("ID_ORG").AsInteger:=BuildDS.FieldByName("ID_ORG")
> .AsInteg er;
> DataBDS.FieldByName("ID_BUILD").AsInteger:=BuildDS.FieldByName("ID")
> .AsInteger;
> DetailDS2.FieldByName("ID_OBJ").AsInteger:=0;
> SaveBtn.Enabled:=True;


В принципе разные знвчения &#151; для стойкости геморроя, очевидно.


> Пользовательские данные в данном случае не в гриде, а в
> DBEdit"ах, ибо зачем под одну строку отводить грид (хотя
> первоначально так у меня и было). Передаются запросом из
> InsertSQL

Блин, тут целый зоопарк каких=то датасетов пасется, хотя на все про все достаточно ровно пяти [25]

B как, интересно, DBEdit, настоленный на другой датасет, успее вставить данные промеж строк вашего кода, пишущий в другой датасет. Или огрызки кода вместо полного фрагмента, приводятся для пущей ясности?


 
grav   (2008-05-20 11:59) [33]


> Интересно, что можно вставить в гриде для таблицы BUILDING(ID,
>  ID_ORG)? Или там ещё поля есть? Почему они тогда не в DATA?
>

Есть еще поля, например коды адреса здания (из справочников).

> Хотя бы дельфийский help по мастер-детайл почитал бы.

Почитал. И в интернете много почитал. Так и не понял логику работы IBDataSet.

> > т.к. IBTable там вкачестве detail.
>
> Остется тихо удалиться :)

IBTable не мешает и работает.


 
grav   (2008-05-20 12:01) [34]


> В принципе разные знвчения — для стойкости геморроя, очевидно.

Ага :) OrganDS=MasterDS
BuildingDS=DetailDS1
Не все поправил, извиняюсь.


 
grav   (2008-05-20 12:03) [35]


> Блин, тут целый зоопарк каких=то датасетов пасется, хотя
> на все про все достаточно ровно пяти

Тк и есть 4 IBDataSet и один IBTable (остался от предыдущей редакции, работает, вот и не заменяю на IBDataSet).


 
grav   (2008-05-20 12:05) [36]

Вот запрос на вставку из InsertSQL
insert into DATA
 (ID_ORG,ID_BUILD,ID_OBJ,GEN_S, LONG_NET, PRISE_B, PRISE_M, IZNOS_B,
IZNOS_M, STEPEN_B,
STEPEN_M,
  WATER, SEWER, HEAT)
values
 (:ID_ORG,:ID_BUILD,:ID_OBJ,:GEN_S, :LONG_NET, :PRISE_B, :PRISE_M,
:IZNOS_B, :IZNOS_M, :STEPEN_B,
  :STEPEN_M, :WATER, :SEWER, :HEAT)


 
ЮЮ ©   (2008-05-20 12:17) [37]

> Вот запрос на вставку из InsertSQL

Какого датасета?


 
ЮЮ ©   (2008-05-20 12:27) [38]

DetailDS2 ?
А какой запрос на выборку?
Он редактируется в гриде или DBEdit-ах. Если второе, то когда делается Insert?


 
grav   (2008-05-20 12:33) [39]

Да, DetailDS2.

Предполагалось, что insert так grav:   (20.05.08 11:46) [30]
Т.е. должна вставиться пустая строка. Потом из dbedit"ов уже Edit.
Но не работает не только вставка, но и редактирование.
SelectSQL
select * from DATA where ID_ORG=:ID_ORG and ID_BUILD=:ID and ID_OBJ=0

ModifySQL
update DATA
set
 GEN_S = :GEN_S,
 LONG_NET = :LONG_NET,
 PRISE_B = :PRISE_B,
 PRISE_M = :PRISE_M,
 IZNOS_B = :IZNOS_B,
 IZNOS_M = :IZNOS_M,
 STEPEN_B = :STEPEN_B,
 STEPEN_M = :STEPEN_M,
 WATER = :WATER,
 SEWER = :SEWER,
 HEAT = :HEAT
where
 ID_ORG = :OLD_ID_ORG and
 ID_BUILD = :OLD_ID_BUILD and
 ID_OBJ = :OLD_ID_OBJ


 
grav   (2008-05-20 12:46) [40]

Убрал для эксперимента из DetailDS2 связывающий DataSource. Все работает.
Вообще тройная связка это нормально (MasterDS-DetailDS1-DetailDS2)?


 
grav   (2008-05-20 13:35) [41]

Догадался я почему не сохраняются данные при редактировании.
Поскольку я использую кэширование, то по нажатию кнопки Выход на форме производится проверка UpdatesPending всех IBDataSet. Если хоть одно UpdatesPending=True, то я делал ApplyUpdates всех пяти датасетов, независимо в каком поменялись данные, но по порядку начиная с MasterDS.
ApplyUpdates видимо надо делать с нижнего уровня связки мастер -детайл.
Лично для меня это не тривиально и до конца не понятно. Объясните, кто может.
Со вставкой я еще не разобрался.


 
grav   (2008-05-20 13:52) [42]

Ой как все криво то.
Загнал добавление новой строки в таблицу DATA в кнопку сохранить.
Сначала подтверждаю добавление новой записи в таблицу BUILDING:
BuildDS.Post;
Потом добавляю новую строку в DATA
DetailDS2.Insert;
DetailDS2.FieldByName("ID_ORG").AsInteger:=DetailDS1.FieldByName("ID_ORG").AsInt eger;
DetailDS2.FieldByName("ID_BUILD").AsInteger:=DetailDS1.FieldByName("ID").AsInteg er;
DetailDS2.FieldByName("ID_OBJ").AsInteger:=0;
DetailDS2.Post;

Остальные поля в таблицу DATA заносятся уже редактированием.


 
Anatoly Podgoretsky ©   (2008-05-20 15:14) [43]

> grav  (20.05.2008 10:40:15)  [15]

У тебя сколько было в школе по математике 100 * 100 <> 1000 далеко не равно.
Слушай, а где это детей допускают до таких больших проектов?
У меня на примете есть хорошая девочка, может возьмете в проект?


 
Anatoly Podgoretsky ©   (2008-05-20 15:14) [44]

> ЮЮ  (20.05.2008 10:43:16)  [16]

Почему может, это вообще то норма.


 
Anatoly Podgoretsky ©   (2008-05-20 15:15) [45]

> Sergey13  (20.05.2008 10:53:19)  [19]

Может, как и организация без зданий.


 
grav   (2008-05-20 15:58) [46]


> Anatoly Podgoretsky ©   (20.05.08 15:14) [43]

Мне вообще то 4-й десяток давно. Ну обшибся, с кем не бывает. Чего мелкие цифры считать то?


> Слушай, а где это детей допускают до таких больших проектов?

Это разве большой проект? Так, мелочь.


 
grav   (2008-05-20 16:00) [47]


> Anatoly Podgoretsky ©   (20.05.08 15:15) [45]

Не может. Производится целевое обследование, есть выборка и чуть более 6 тыс организаций. У всех есть здания, во всх зданиях есть объекты.


 
grav   (2008-05-20 16:03) [48]


> Anatoly Podgoretsky ©

Лучше бы по делу написали что нибудь. Вроде бы не раз от вас получал дельные советы.

Непонятна логика (правила) работы с IBDataSet. В интернете не нашел ничего.
Вот есть MasterDS-DetailDS1-DetailDS2. Делается вставка в DetailDS1 и DetailDS2.
Каков порядок Insert и Post в этих двух датасетах?


 
Anatoly Podgoretsky ©   (2008-05-20 16:28) [49]

> grav  (20.05.2008 15:58:46)  [46]

Ни фига себе мелкие, на 54 миллиона записей ошибся


 
Anatoly Podgoretsky ©   (2008-05-20 16:29) [50]

grav   (20.05.08 16:00) [47]
Жизнь она накажет строго.
Так как насчет девочки то?


 
Sergey13 ©   (2008-05-20 16:39) [51]

> [42] grav   (20.05.08 13:52)

Я кажется понял твою проблему.
Итак:
В мастер новая запись вставляется, в первый детайл вставляется, в во второй детайл не вставляется? Так?
Похоже на то что первый детайл при посте не знает ID своей новой зписи. Он узнает ее при переоткрытии.
Установлено ли свойство GeneratorField (кажется так называется) у первого детайла (который здания)?
И вообще, при заведении связанных М-Д данных пользоваться "гридовой" логикой не совсем правильно, ИМХО.


 
grav   (2008-05-20 17:50) [52]


> Anatoly Podgoretsky ©   (20.05.08 16:29) [50]


> Так как насчет девочки то?

Она в Нижнем Новгороде что ли?


 
grav   (2008-05-21 09:34) [53]


> Sergey13 ©   (20.05.08 16:39) [51]


> В мастер новая запись вставляется, в первый детайл вставляется,
>  в во второй детайл не вставляется? Так?

Да, так.
Вот так вставляется >grav   (20.05.08 13:52) [42]
Видимо надо делать так:

MasterDS.Insert;
.....
MasterDS.Post;
DetailDS1.Insert;
...
DetailDS1.Post;
DetailDS2.Insert;
....
DetailDS2.Post;

И нельзя так:

MasterDS.Insert;
DetailDS1.Insert;
DetailDS2.Insert;
...
MasterDS.Post;
DetailDS1.Post;
DetailDS2.Post;


 
Sergey13 ©   (2008-05-21 09:55) [54]

> [53] grav   (21.05.08 09:34)
> И нельзя так:

Ну это в общем то и логично. Я и писал об этом

> [51] Sergey13 ©   (20.05.08 16:39)
> при заведении связанных М-Д данных пользоваться "гридовой"
> логикой не совсем правильно, ИМХО.

Ты вставляешь связанные многоуровневые данные. Данные верхнего уровня необходимы для данных нижнего. Но БД на момент ввода их не знает - отсюда и проблемы.
Я такие вставки предпочитаю делать используя таблицы в памяти (типа RxMemoryData). Заполняю их вводимыми сущностями, а потом (по кнопке Сохранить) одной транзакцией вставляю их в БД с помощью скрипта.


 
Виталий Панасенко ©   (2008-05-21 10:30) [55]

А что, было так ?!

> MasterDS.Insert;
> DetailDS1.Insert;
> DetailDS2.Insert;
> ...
> MasterDS.Post;
> DetailDS1.Post;
> DetailDS2.Post;


 
grav   (2008-05-21 10:54) [56]


> Sergey13 ©   (21.05.08 09:55) [54]


> Я такие вставки предпочитаю делать используя таблицы в памяти

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


 
Sergey13 ©   (2008-05-21 10:57) [57]

> [56] grav   (21.05.08 10:54)

Это просто компоненты типа датасет (со всеми вытекающими от сюда свойствами) которые не опираются ни на какие данные из БД. Типа временных таблиц, но не сервере, а на клиенте.


 
grav   (2008-05-21 11:01) [58]


> Виталий Панасенко ©   (21.05.08 10:30) [55]
> А что, было так ?!

Да, было - grav   (20.05.08 11:46) [30]
Мне представлялось логичным это. Т.к. обычно для вставки я использовал IBQuery, последовательно исполняя запросы.
В чем вообще смысл Insert и Post?
Что происходит при выполнении данных команд (или чего это)?
У меня сложилось впечатление, что Insert - означает использование запроса из InsertSQL и больше ничего. Post, видимо, аналогичен IBQuery.ExecSQL; Я прав?


 
Виталий Панасенко ©   (2008-05-21 14:51) [59]


> У меня сложилось впечатление, что Insert - означает использование
> запроса из InsertSQL и больше ничего. Post, видимо, аналогичен
> IBQuery.ExecSQL; Я прав?

примерно...это все сделано, ИМХО, для однотипности оперций..все наследники TDataSet имеют переопределенные методы insert/Append/AppendRecord/Delete/Edit.. только для разных движков содержимое разное.. для Paradox Edit еще и блокирует запись, для остальных по разному


 
grav   (2008-05-22 10:57) [60]

Вопрос не в тему.
Есть в таблице поле Load типа Integer. Произвожу вставку данных через параметр :LOAD из поля LoadEd (TEdit).
AddSQL.ParamByName("Load").AsString:=LoadEd.Text;

Когда поле LoadEd пустое, через раз работает без ошибок, через раз ошибка конвертирования из строки "".


 
Reindeer Moss Eater ©   (2008-05-22 11:01) [61]

через раз ошибка конвертирования из строки "".

А ты вызывай exec через этот раз и будет счастье


 
grav   (2008-05-22 11:22) [62]

Через раз это вот почему.
В таблицу в пределах одной транзакции вставляется несколько записей.
Если в предыдущей записи данные в поле присутствуют, то при вставке очередной записи с нулевым полем вылетает ошибка. Если запись с нулевым полем первая, то ошибку нет.
Чего не так то?


 
Sergey13 ©   (2008-05-22 11:33) [63]

> [62] grav   (22.05.08 11:22)
> Чего не так то?

Например цикл как-нибудь криво написан. Но ты же реальный код не даешь - одни огрызки.


 
Reindeer Moss Eater ©   (2008-05-22 11:37) [64]

Чего не так то?

Тебе про это сама ошибка своим текстом рассказывает. Что там у тебя не так.


 
grav   (2008-05-22 12:10) [65]

Вот такой запрос
INSERT INTO DATA (ID_ORG, ID_BUILD, ID_OBJ, GEN_S, LONG_NET,PRISE_B,PRISE_M,"+
       "IZNOS_B, IZNOS_M,STEPEN_B, STEPEN_M, WATER, SEWER, HEAT, ID_MATERIAL )"+
        " values (:ID_ORG,:ID_BUILD,:ID_OBJ,:GEN_S, :LONG_NET,:PRISE_B,:PRISE_M,"+
       ":IZNOS_B, :IZNOS_M,:STEPEN_B, :STEPEN_M, :WATER, :SEWER, :HEAT, :ID_MATERIAL)


Вот так вот вводятся параметры
AddSQL.ParamByName("Load").AsString:=LoadEd.Text;

Оказывается эта ошибка (conversion error from string "") не только по этому полю вылезает, но и по другим пустым, если они при вставке предыдущей записи не были пустыми


 
Reindeer Moss Eater ©   (2008-05-22 12:18) [66]

странно, да?


 
Sergey13 ©   (2008-05-22 12:21) [67]

> [65] grav   (22.05.08 12:10)

Перед присвоением значения параметру анализируй значение LoadEd.Text на пустоту и меняй параметр соответственно.

но вот странно, что

> Если запись с нулевым полем первая, то ошибку нет.

все таки в цикле может быть косяк, ИМХО.


 
grav   (2008-05-22 12:23) [68]


> Reindeer Moss Eater ©   (22.05.08 12:18) [66]

Чего не так то?
Если выполнить этот запрос с LoadEd.Text:=""; Будет все ОК.
Если выполнить с LoadEd.Text<>""; Тоже все ОК.
А если в пределах одной транзакции две вставки сделать сначала с LoadEd.Text<>"" а потом с LoadEd.Text:="" будет ошибка.


 
Reindeer Moss Eater ©   (2008-05-22 12:25) [69]

какие у тебя умные транзакции.
знают о существовании эдитов и о том, что в них написано.


 
grav   (2008-05-22 12:26) [70]


> Sergey13 ©   (22.05.08 12:21) [67]

Нет циклов никаких.
Если анализировать каждый TEdit на пустоту, то для каждого придется переменную заводить.
И вообще, зачем тогда параметры? Формировал бы каждый раз новый запрос и все. Вроде бы параметры как раз и нужны для облегчения задачи этой.


 
grav   (2008-05-22 12:28) [71]


> Reindeer Moss Eater ©   (22.05.08 12:25) [69]

Ну докопаться до чего угодно можно. А вот ответить трудно. Правда, чтобы ответить еще и знать нужно.


 
Reindeer Moss Eater ©   (2008-05-22 12:29) [72]

А если в пределах одной транзакции две вставки сделать сначала с LoadEd.Text<>"" а потом с LoadEd.Text:="" будет ошибка.

первое присвоение с неравно типизирует параметр.
после этого в параметре при присвоениях ожидается адекватное значение, а не абракадабкра.


 
Reindeer Moss Eater ©   (2008-05-22 12:39) [73]

Есть в таблице поле Load типа Integer. Произвожу вставку данных через параметр :LOAD из поля LoadEd (TEdit).
AddSQL.ParamByName("Load").AsString:=LoadEd.Text;


это так в автошколе учили? с целочисленными полями работать через строки?


 
grav   (2008-05-22 12:46) [74]


> Reindeer Moss Eater ©   (22.05.08 12:39) [73]

Угу, в автошколе.
А надо сначала завести для каждого TEdit переменную, потом проверить не пустое ли поле и если пустое присвоить переменной NULL.
AddSQL.ParamByName("Load").AsInteger:=NULL; ?
Или другой алгоритм есть?


 
Reindeer Moss Eater ©   (2008-05-22 12:50) [75]

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


 
Reindeer Moss Eater ©   (2008-05-22 12:51) [76]

AddSQL.ParamByName("Load").Clear


 
grav   (2008-05-22 12:56) [77]


> Reindeer Moss Eater ©   (22.05.08 12:51) [76]
> AddSQL.ParamByName("Load").Clear

Это если NULL вставить нужно?


 
grav   (2008-05-22 13:04) [78]


> Reindeer Moss Eater ©   (22.05.08 12:51) [76]
> AddSQL.ParamByName("Load").Clear

Да, так работает. спасибо.
Вот только не радует наличие такого кода для каждого поля:

if LoadEd.Text="" then
    AddSQL.ParamByName("LOAD").Clear
  else
    AddSQL.ParamByName("LOAD").AsString:=LoadEd.Text;


 
Sergey13 ©   (2008-05-22 13:36) [79]

> [70] grav   (22.05.08 12:26)
> Нет циклов никаких.

Откуда тогда всякие солова типа "если они при вставке предыдущей записи не были пустыми" берутся?

Вобщем мой телепатор перегрелся и сдох. Я пас.


 
grav   (2008-05-22 13:53) [80]


> Sergey13 ©   (22.05.08 13:36) [79]

Спасибо, что не бросаете :)
Данные вводит пользователь. Если под циклом имелась ввиду работа пользователя, то да он есть :) Пользователь вводит данные организации, потом данные первого здания, потом данные объектов первого здания, потом вводит данные второго здания, обекты второго здания и т.д.


 
Sergey13 ©   (2008-05-22 14:20) [81]

> [80] grav   (22.05.08 13:53)

А нужен ли в этих полях NULL? Может проще заполнять значения по умолчанию 0? Например на onNewRecord датасета. Или на потерю фокуса едита.

В любом случае это косяк в программе, ИМХО, если

> [62] grav   (22.05.08 11:22)
> Если в предыдущей записи данные в поле присутствуют, то
> при вставке очередной записи с нулевым полем вылетает ошибка.
> Если запись с нулевым полем первая, то ошибку нет.


 
ANB   (2008-05-22 14:45) [82]


> Да, так работает. спасибо.
> Вот только не радует наличие такого кода для каждого поля:
>
>
> if LoadEd.Text="" then
>     AddSQL.ParamByName("LOAD").Clear
>   else
>     AddSQL.ParamByName("LOAD").AsString:=LoadEd.Text;

Особенность ИБ/ФБ, для которого пустая строка и нулл - разные значения.

Не скажу, что плохая особенность, но однако . . .


 
grav   (2008-05-23 10:02) [83]

Объясните еще пожалуйста одну вещь по транзакциям.
После того как я сделал MainForm.WriteTr.Commit; почему данные становятся доступными только после отключения/подключения к БД?
И соответственно, если не произвести отключение/подключение, то есть возможность забить дублирующие данные


 
Reindeer Moss Eater ©   (2008-05-23 10:08) [84]

Потому что транзакции разные и читающая транзакция должна завершиться и начаться заново. Реконнект для этого не нужен (если конечно транзакциями кто-то управляет).


 
grav   (2008-06-11 13:07) [85]

Снова проблемка, помогите пожалуйста.
Имеется DBGrid со списком зданий и соответствующий IBDataSet (мастер) к нему. Имеется набор DBEdit"ов с соответствующим IBDataSet (детайл). IBDataSet"ы в режиме CachedUpdates.
Меняю данные в DBEdit, делаю ApplyUpdates. Данные сохраняются. Все ОК.
Делаю много изменений в таком порядке:
Меняю данные в DBEdit, выбираю новое здание, меняю данные в DBEdit и т.д.
Делаю ApplyUpdates. Сохраняются измененные данные только у последнего здания.
Как сохранить все изменения за раз не нажимая каждый раз кнопку сохранить?


 
Поросенок Винни-Пух ©   (2008-06-11 13:13) [86]

при смене мастер записи детайл датасет переоткрывается. закешированные изменения потерялись если не было апплая.


 
Поросенок Винни-Пух ©   (2008-06-11 13:28) [87]

Как сохранить все изменения за раз не нажимая каждый раз кнопку сохранить?

Выключить cachedupdates


 
grav   (2008-06-11 13:57) [88]


> Поросенок Винни-Пух ©   (11.06.08 13:28) [87]
>
> Выключить cachedupdates

Если я выключу, то как отслежу что изменения были?


 
Поросенок Винни-Пух ©   (2008-06-11 13:59) [89]

а зачем тебе "отслеживать изменения", которые ты сам же и теряешь?


 
Anatoly Podgoretsky ©   (2008-06-11 14:03) [90]

> grav  (11.06.2008 13:57:28)  [88]

Отслеживать не надо, должна быть сладкая парочка Insert + Commit


 
grav   (2008-06-11 14:10) [91]


> Поросенок Винни-Пух ©   (11.06.08 13:59) [89]
> а зачем тебе "отслеживать изменения", которые ты сам же
> и теряешь?

Форма большая, данных много. Жмет пользователь кнопку Выход, ему выдается сообщение, что данные изменились, сохранить? Да, НЕТ.
Если пользователь чего то менял, жмет Да и commit, если не менял, а случайно чего нибудь изменил, жмет НЕТ и rollback.


 
Поросенок Винни-Пух ©   (2008-06-11 14:12) [92]

и чо?
TDataSet.State in dsEditMode тоже скажет что возможно были изменения и нужен либо пост либо кансел


 
Поросенок Винни-Пух ©   (2008-06-11 14:13) [93]

тебе уже сказано куда деваются все изменения кроме последнего редактирования.


 
grav   (2008-06-11 14:18) [94]

Сейчас добавил ApplyUpdates в событие BeforeScroll, может это и плохо, но все сохраняется.
Правда это не выход, так как если скроллинг был, а следующих изменений не было, сообщение не будет выведено и коммита не будет


 
grav   (2008-06-11 14:19) [95]


> Поросенок Винни-Пух ©   (11.06.08 14:13) [93]

так я понял, но ищу варианты обхода


 
Поросенок Винни-Пух ©   (2008-06-11 14:21) [96]

Сейчас добавил ApplyUpdates в событие BeforeScroll

Читай по губам:
При смене мастер записи детайл датасет переоткрывается.
В переводе с древнегреческого это означает, что он сначала закрывается, потом открывается снова.


 
grav   (2008-06-11 14:31) [97]


> Поросенок Винни-Пух ©   (11.06.08 14:21) [96]
> Сейчас добавил ApplyUpdates в событие BeforeScroll
>
> Читай по губам:
> При смене мастер записи детайл датасет переоткрывается.
> В переводе с древнегреческого это означает, что он сначала
> закрывается, потом открывается снова

Да понял я. Закрытие-открытие и измененные данные потеряны.
Если я делаю ApplyUpdates перед переходом к другой записи, то изменеия сохраняются.
Можно поподробнее про TDataSet.State in dsEditMode? Чтобы можно было от CachedUpdates отказаться?


 
Поросенок Винни-Пух ©   (2008-06-11 14:33) [98]

Ничего ты не понял.
Перед закрытием есть бефослоз


 
grav   (2008-06-11 14:46) [99]


> Поросенок Винни-Пух ©   (11.06.08 14:33) [98]

Ну да, про BeforeClose я не подумал. Но пользы в моем случае от него не больше, чем от BeforeScroll.


 
Поросенок Винни-Пух ©   (2008-06-11 14:49) [100]

Но пользы в моем случае от него не больше, чем от BeforeScroll.

ага, особенно если скрола вообще не было


 
grav   (2008-06-11 14:56) [101]

Поставил переменную в BeforeClose. Теперь, если были ApplyUpdates то переменная выставляется в 1 и на выходе сообщение об изменении данных.
Спасибо!


 
grav   (2008-06-11 15:00) [102]


> Поросенок Винни-Пух ©   (11.06.08 14:49) [100]

Если скрола не было, это хорошо, изменения отслеживаются. А вот если изменения были, потом скрол и потом не было изменений, то получается UpdatesPending:=False, именения которые были перед скролом теряются.
И тут уж все равно где был ApplyUpdates в BeforeScroll или  BeforeClose.


 
grav   (2008-06-11 15:16) [103]

Только не бейте :) У меня еще вопрос.
Есть DBGrid, в нем 10 записей. На экране видно только 5. Пользователь жмут стрелку вниз на скроле и указатель перемещается сразу на 6-ю запись (на первую невидимую).
Можно как то сделать, чтобы нажатие на кнопку вниз перемещало курсор на одну запись вниз начиная с первой?
PS
Это пользователи хотят, а вовсе не я извращенец :)


 
MsGuns ©   (2008-06-12 16:46) [104]

>grav   (11.06.08 14:10) [91]
>Жмет пользователь кнопку Выход, ему выдается сообщение, что данные изменились, сохранить? Да, НЕТ.
>Если пользователь чего то менял, жмет Да и commit, если не менял, а случайно чего нибудь изменил, жмет НЕТ и rollback.

Совершенно убитая технология в угоду юзеру, причитающему "сделайте как в эксель"

По сути сабжа вообще промолчу ибо там такое нагорожено ;(
Похоже на фонд имущества или страхкомпанию - не лучше ли взять 1С вариант и просто посмотреть как там все организовано ?

>grav   (11.06.08 15:16) [103]
>Только не бейте :) У меня еще вопрос.
>Есть DBGrid, в нем 10 записей. На экране видно только 5. Пользователь жмут стрелку >вниз на скроле и указатель перемещается сразу на 6-ю запись (на первую невидимую).
>Можно как то сделать, чтобы нажатие на кнопку вниз перемещало курсор на одну >запись вниз начиная с первой?

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

>Это пользователи хотят, а вовсе не я извращенец :)

Еще один "убойный" аргумент. А если пользователь изъявит желание работать лежа - Вы ему свою форму на 90 градусов повернете ?
Советую почитать статьи о хорошем стиле проектирования пользовательских интерфейсов. В тырнете их моря.



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

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

Наверх





Память: 0.74 MB
Время: 0.009 c
15-1211909535
Ega23
2008-05-27 21:32
2008.07.13
Чем читать DJVU-файлы?


2-1213618244
Муслик
2008-06-16 16:10
2008.07.13
Текст из файла


2-1211262319
grav
2008-05-20 09:45
2008.07.13
IBDataSet, Master-Detail и Insert


2-1213341653
Dmitry
2008-06-13 11:20
2008.07.13
Canvas


15-1211778536
AndreyV
2008-05-26 09:08
2008.07.13
Phoenix приземлился на Марс





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский