|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#31
|
||||
|
||||
Цитата:
Цитата:
Выше в теме я почти ответил на вопрос про книги и знания. Даже не уверен, что читал где-то, а не вывел самостоятельно. Это математика, в ней всё просто, -- недостающее можно вывести и самому. А чтобы теория не расходилась с практикой, достаточно помнить, что все теории делятся на верные и неполные. Цитата:
Цитата:
Не стоит путать форумы с богадельнями. © Bargest |
#32
|
||||
|
||||
Я поймал волну. Осталось совсем чуть-чуть. Вопрос:
Как реализовать вызов из диалога другого диалога? Ведь в той же 1c можно вызвать справочник товаров или клиентов, для заполнения соответствующих полей основного документа? Получается Основная форма -> Диалог оформления Документа -> Диалог выбора клиента (или товаров, или ещё Бог знает чего) Это ж как нужно пробрасывать DataSet'ы с главной формы?) И отклоняясь от темы. Насколько адекватно создавать одинаковые ADOTable на разных формах с одной и той же Таблицей внутри? Или ADOQuery с одним и тем же запросом. Вообще у меня сложилось впечатление, что ADOTable =(тождественно) ADOQuery(Select * from TableName) P.S. Есть одна новость по поводу первичной задачи "добавлять" с возможностью отмены и при этом ещё Master-Detail связь держать. Если организовать вот такой алгоритм: (при этом LockType оставить ltOptimistic): Код:
procedure TFormMain.dxBarLargeButton1Click(Sender: TObject); begin Connection.BeginTrans; try with TFormTicketDialog.Create(Self) do try Execute(Tickets) finally Free; end; Connection.CommitTrans; except on E: Exception do Connection.RollbackTrans; end; end; Код:
Connection.CommitTrans; Только тогда на mrOK нужно повесть CommitTrans, а на mrCancel RollbackTrans. Вместо Post и Cancel. Я прав? Последний раз редактировалось Uniq!, 17.10.2013 в 14:16. |
#33
|
||||
|
||||
Цитата:
Если справочники считаются временными сущностями, их наборы данных хранятся прямо в диалогах и создаются/уничтожаются по мере надобности вместе с самими диалогами. В этом случае списки клиентов на главной форме и в диалогах могут выводиться разными наборами данных. На то и СУБД, в конце концов. Если же перечитывание справочников при каждом вызове диалога считается затратной операцией, придумывается что-то вроде диспетчера ресурсов, разделяющего однажды прочитанные данные между многими вызовами диалогов. В простом случае в роли диспетчера может выступить и модуль данных, и даже глобальная переменная. Развитие идет по спирали, и осознанное использование спорных инструментов -- сознательный выбор, пусть даже они и были признаны "плохими" на предыдущем шаге. Инструменты ведь не бывают плохими или хорошими, они всего лишь инструменты. Сравни свои теперешние знания о глобальных переменных и модулях данных с культом карго, который был раньше. Если вместо "проброса" справочников сделать объект "окружение", в его роли вполне может выступить модуль данных с дополнительными публичными методами по принципу Execute, если нужно. Цитата:
Не стоит путать форумы с богадельнями. © Bargest |
#34
|
||||
|
||||
Прошла уже куча времени, а я опять сталкиваюсь с проблемой заполнения связанных таблиц.
И всё также адекватного решения с Commit и RollBack не нашёл. Продолжаю поиски. Гвоздь вбит именно там, где необходимо присвоить подчинённым данным ещё "незаCommit'ченый" ID главной записи. google: транзакции и связанные таблицы в ADO |
#35
|
|||
|
|||
хм...
Смотрю я на все это и думаю, а парень то изобретает велосипед.
Возьми Delphi, Firebird, IBExpert, FIBPlus и забудь про изврат, которым ты занимаешься. |
#36
|
||||
|
||||
Почему велосипед? Вы сейчас предлагаете четырехлетний проект перевести на другой движок бд. Я молчу про то, что база уже около 8гигов весит, и все прекрасно работает без подвисаний. меня лишь внутреннее устройство приложения не радует.
Слабо представляю как вышеупомянутые средства помогут решить вопрос присвоения в дочернюю таблицу autoinc Id из родительской. |
#37
|
|||
|
|||
Выбор всегда есть.
Был у меня проект, который я пару лет делал на парадоксе, как только узнал про FB, сразу понял, что проект нужно переводить на него.
Очень рекомендую ознакомится с возможностями FB. Очень простой и мощный язык хранимых процедур. Независимые от транзакций генераторы (id в вашем случае). Возможность создавать любые внешние функции. Наличие триггеров, позволяет возложить всю логику и поддержание целостности на сервер. И много еще чего. FIBPlus умеет кэшировать изменения и генерировать ID еще до того, как данные попадут на сервер, а значит вы можете без проблем создать запись в мастер таблице, узнать ее ID еще до коммита, и присвоить этот ID дочерним таблицам. Но этого вам делать не придется, FIB все сделает за вас. Но в данном случае ID генерируется правильно, в рамках механизма заложенного FB, для всех пользователей он будет уникальный. Посмотрите примеры использования FIBPlus. Просто я смотрю, как вы стараетесь, ищете решения, но все уже давно придумано, просто вам нужно освежить свои знания, пересмотреть подход... На своем опыте, хочу сказать, что после замарочек с парадоксом, я освоил работу с FB буквально за месяц и был несказанно рад, оно действительно того стоит. Последний раз редактировалось kaakaa, 04.09.2014 в 11:33. |
Этот пользователь сказал Спасибо за это полезное сообщение: | ||
Uniq! (04.09.2014)
|
#38
|
||||
|
||||
Цитата:
|
#39
|
|||
|
|||
Как я понимаю, мы имеем один документ и много изделий связанных с ним.
Нужно, чтобы добавление/изменение нескольких изделий происходили в рамках одной транзакции. Если записи будут коммититься в разных транзакциях, возможно ситуация, когда другой пользователь сделает запрос к документу, но увидит не все связанные с ним изделия. ВАРИАНТЫ: Как можно решить эту проблемму: 1) Кэшировать изменения/вставку. После того как пользователь закончил ввод, он нажимает кнопку сохранить и все данные коммитятся в рамках одной транзакции. Если датасет не умеет кэшировать данные, можно сделать прослойку в виде временной таблицы, вы делали это через MemTable. Но при коммите прийдется использовать last_insert_id( ) чтобы получить id мастера. 2) Проблема получения ID мастер таблицы актуальна. Вероятно, решить ее в рамках мускула можно вставкой записи без подтверждения транзакции и выполнив last_insert_id( ). Это предположение, его я не проверял. Зная ID мастер-записи, вы можете добавлять записи в дечернюю таблицу в рамках активной транзакции в которой была выполнена вставка мастер-записи. Если пользователь захочет все отменить, он просто откатит транзакцию. Если захочет все применить, он ее прокоммитит. Пока транзакция не подтверждена, другие пользователи не видят записи, которые были в ней созданы. Недостатком этого подхода можно считать длинную WRITE транзакцию, которая косвенно может блокировать часть данных. Однако, это плохой тон. Последний раз редактировалось kaakaa, 04.09.2014 в 12:56. |
Этот пользователь сказал Спасибо за это полезное сообщение: | ||
Uniq! (08.09.2014)
|
#40
|
||||
|
||||
kaakaa, реализовал пока следующим образом:
создал хранимку такого вот вида: Код:
DELIMITER $$ USE `pawnshop`$$ DROP PROCEDURE IF EXISTS `ItemAdd`$$ CREATE PROCEDURE `ItemAdd` ( IN aTicketID INT, IN aInfo VARCHAR(32), IN aStandard INT, IN aFullWeight DECIMAL(10,2), IN aInsWeight DECIMAL(10,2), IN aPriceP1g DECIMAL(10,2), OUT aNewID INT ) BEGIN INSERT INTO `items` ( TicketID, iInfo, iStandard, iFullWeight, iInsWeight, iPriceP1g ) VALUES ( aTicketID, aInfo, iStandard, aFullWeight, aInsWeight, aPriceP1g ) ; SET aNewID = @@Identity ; END $$ DELIMITER ; Внутри программы с главной формы зову модальную форму, и перед этим открываю транзакцию: (внутрь отдаю Connection, чтоб там уже с ним связать AddTicketCom: TADOStoredProc) Код:
procedure TFormMain.btnAddTicketClick(Sender: TObject); begin TicketsView.BeginUpdate; with TFormTicketNew.Create(Application) do try Connection.BeginTrans; if AddTicket(Connection) then Connection.CommitTrans else Connection.RollbackTrans; finally Free; end; TicketsView.EndUpdate; end; Внутрь самой процедуры AddTicket: Код:
function TFormTicketNew.Execute(iConnection: TADOConnection): boolean; begin AddTicketCom.Connection := iConnection; while not Result do begin Result := ShowModal = mrOk; if VarIsNull(edParamPerson.EditValue) then begin MessageBox(Handle, pChar('Вы не указали информацию о Клиенте.'), pChar('Неверные сведения'), MB_ICONERROR or MB_OK); edParamPerson.SetFocus; Result := false; Continue; end; if VarIsNull(edParamLoan.EditValue) then begin MessageBox(Handle, pChar('Вы не указали информацию о Ссуде.'), pChar('Неверные сведения'), MB_ICONERROR or MB_OK); edParamLoan.SetFocus; Result := false; Continue; end; end; AddTicket.Parameters.ParamByName('PawnshopID').Value := 1; AddTicket.Parameters.ParamByName('StatusID').Value := 1; AddTicket.Parameters.ParamByName('iNo').Value := 10000; AddTicket.Parameters.ParamByName('iStartDate').Value := Date; AddTicket.Parameters.ParamByName('iEndDate').Value := IncDay(Date, 29); AddTicket.Execute; // использую вот это AddTicket.Parameters.ParamByName('NewID').Value; для дальнейшего добавления в подчинённую таблицу end; Не могу никак организовать логику: у меня есть проверки на заполненные поля. Если поле не заполнено, форма не должна уничтожаться (т.е. нужен While цикл) и при этом ещё нужно как-то обрабатывать когда модальную форму просто закрывают) Конструкция пока видится ... не видится Последний раз редактировалось Uniq!, 08.09.2014 в 13:05. |
#41
|
|||
|
|||
Смотри TForm.OnCloseQuery.
В этом обработчике ты определяешь, были сделаны изменения в данных или нет. Классика обработки: 1) Пользователь закрывает форму (нажимает кнопку закрыть и т.п.); 2) Диалог сохранения данных; 3) Пользователь не хочет сохранять данные, тогда ROLLBACK; 4) Пользователь хочет сохранять данные, тогда проверка и если все ОК, то COMMIT. Последний раз редактировалось kaakaa, 08.09.2014 в 13:23. |