Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Базы данных
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #31  
Старый 16.10.2013, 19:14
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от Uniq!
А меня в институте приучили, что чем проще, тем лучше.
Всё гениальное -- просто. В остальных случаях простота хуже воровства.

Цитата:
Сообщение от Uniq!
1) Значит я создаю форму - диалог. (исключаю её из автосоздаваемых) ВОТ это лишнее телодвижение почему-то не надо удалять.
На самом деле удалять нужно не только автосоздаваемую форму, но и ее переменную из модуля, чтобы не было больше соблазнов. Это мой первый совет для начинающих. В идеале в проекте должна быть всего одна глобальная переменная -- главная форма. Все остальные, чтобы выжить, должны упоминаться в секциях initialization/finalization модулей.

Выше в теме я почти ответил на вопрос про книги и знания. Даже не уверен, что читал где-то, а не вывел самостоятельно. Это математика, в ней всё просто, -- недостающее можно вывести и самому. А чтобы теория не расходилась с практикой, достаточно помнить, что все теории делятся на верные и неполные.

Цитата:
Сообщение от Uniq!
Это оказывается шаблонизированная структура
Первый раз вижу такое словоупотребление. Вроде в теме на SQL.ru упоминается обычное визуальное наследование. Наш абстрактный диалог под него и придумывался.

Цитата:
Сообщение от Mrak
не покидает ощущение, что у меня быдлокод везде
Раз не покидает -- надежда есть.
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #32  
Старый 17.10.2013, 14:09
Аватар для Uniq!
Uniq! Uniq! вне форума
Местный
 
Регистрация: 29.09.2010
Сообщения: 539
Версия Delphi: Delphi XE3
Репутация: 374
По умолчанию

Я поймал волну. Осталось совсем чуть-чуть. Вопрос:
Как реализовать вызов из диалога другого диалога? Ведь в той же 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;
, то ID этого билета можно получить (заPOSTив билет) ещё до выполнения строки
Код:
Connection.CommitTrans;
, т.е. с возможностью отмены.

Только тогда на mrOK нужно повесть CommitTrans, а на mrCancel RollbackTrans. Вместо Post и Cancel. Я прав?

Последний раз редактировалось Uniq!, 17.10.2013 в 14:16.
Ответить с цитированием
  #33  
Старый 17.10.2013, 15:47
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от Uniq!
Как реализовать вызов из диалога другого диалога? Ведь в той же 1c можно вызвать справочник товаров или клиентов, для заполнения соответствующих полей основного документа?
Это уже архитектурный вопрос.

Если справочники считаются временными сущностями, их наборы данных хранятся прямо в диалогах и создаются/уничтожаются по мере надобности вместе с самими диалогами. В этом случае списки клиентов на главной форме и в диалогах могут выводиться разными наборами данных. На то и СУБД, в конце концов.

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

Развитие идет по спирали, и осознанное использование спорных инструментов -- сознательный выбор, пусть даже они и были признаны "плохими" на предыдущем шаге. Инструменты ведь не бывают плохими или хорошими, они всего лишь инструменты. Сравни свои теперешние знания о глобальных переменных и модулях данных с культом карго, который был раньше.

Если вместо "проброса" справочников сделать объект "окружение", в его роли вполне может выступить модуль данных с дополнительными публичными методами по принципу Execute, если нужно.

Цитата:
Сообщение от Uniq!
Только тогда на mrOK нужно повесть CommitTrans, а на mrCancel RollbackTrans. Вместо Post и Cancel. Я прав?
Я бы предусмотрел два вида диалогов -- простой и подчиненными данными, тогда Execute становится виртуальной.
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #34  
Старый 26.07.2014, 18:30
Аватар для Uniq!
Uniq! Uniq! вне форума
Местный
 
Регистрация: 29.09.2010
Сообщения: 539
Версия Delphi: Delphi XE3
Репутация: 374
По умолчанию

Прошла уже куча времени, а я опять сталкиваюсь с проблемой заполнения связанных таблиц.
И всё также адекватного решения с Commit и RollBack не нашёл.
Продолжаю поиски. Гвоздь вбит именно там, где необходимо присвоить подчинённым данным ещё "незаCommit'ченый" ID главной записи.

google: транзакции и связанные таблицы в ADO
Ответить с цитированием
  #35  
Старый 04.09.2014, 00:14
kaakaa
 
Сообщения: n/a
По умолчанию хм...

Смотрю я на все это и думаю, а парень то изобретает велосипед.

Возьми Delphi, Firebird, IBExpert, FIBPlus и забудь про изврат, которым ты занимаешься.
Ответить с цитированием
  #36  
Старый 04.09.2014, 01:19
Аватар для Uniq!
Uniq! Uniq! вне форума
Местный
 
Регистрация: 29.09.2010
Сообщения: 539
Версия Delphi: Delphi XE3
Репутация: 374
По умолчанию

Почему велосипед? Вы сейчас предлагаете четырехлетний проект перевести на другой движок бд. Я молчу про то, что база уже около 8гигов весит, и все прекрасно работает без подвисаний. меня лишь внутреннее устройство приложения не радует.

Слабо представляю как вышеупомянутые средства помогут решить вопрос присвоения в дочернюю таблицу autoinc Id из родительской.
Ответить с цитированием
  #37  
Старый 04.09.2014, 11:27
kaakaa
 
Сообщения: n/a
По умолчанию Выбор всегда есть.

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

Очень рекомендую ознакомится с возможностями FB.
Очень простой и мощный язык хранимых процедур.
Независимые от транзакций генераторы (id в вашем случае).
Возможность создавать любые внешние функции.
Наличие триггеров, позволяет возложить всю логику и поддержание целостности на сервер.
И много еще чего.

FIBPlus умеет кэшировать изменения и генерировать ID еще до того, как данные попадут на сервер, а значит вы можете без проблем создать запись в мастер таблице, узнать ее ID еще до коммита, и присвоить этот ID дочерним таблицам. Но этого вам делать не придется, FIB все сделает за вас.
Но в данном случае ID генерируется правильно, в рамках механизма заложенного FB, для всех пользователей он будет уникальный.

Посмотрите примеры использования FIBPlus.

Просто я смотрю, как вы стараетесь, ищете решения, но все уже давно придумано, просто вам нужно освежить свои знания, пересмотреть подход...

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

Последний раз редактировалось kaakaa, 04.09.2014 в 11:33.
Ответить с цитированием
Этот пользователь сказал Спасибо за это полезное сообщение:
Uniq! (04.09.2014)
  #38  
Старый 04.09.2014, 12:10
Аватар для Uniq!
Uniq! Uniq! вне форума
Местный
 
Регистрация: 29.09.2010
Сообщения: 539
Версия Delphi: Delphi XE3
Репутация: 374
По умолчанию

Цитата:
Сообщение от kaakaa
оно действительно того стоит.
Прислушаюсь, пожалуй. Спасибо.
Ответить с цитированием
  #39  
Старый 04.09.2014, 12:36
kaakaa
 
Сообщения: n/a
По умолчанию

Как я понимаю, мы имеем один документ и много изделий связанных с ним.

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

ВАРИАНТЫ:

Как можно решить эту проблемму:
1) Кэшировать изменения/вставку. После того как пользователь закончил ввод, он нажимает кнопку сохранить и все данные коммитятся в рамках одной транзакции. Если датасет не умеет кэшировать данные, можно сделать прослойку в виде временной таблицы, вы делали это через MemTable.
Но при коммите прийдется использовать last_insert_id( ) чтобы получить id мастера.

2) Проблема получения ID мастер таблицы актуальна. Вероятно, решить ее в рамках мускула можно вставкой записи без подтверждения транзакции и выполнив last_insert_id( ). Это предположение, его я не проверял.

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

Если пользователь захочет все отменить, он просто откатит транзакцию. Если захочет все применить, он ее прокоммитит.

Пока транзакция не подтверждена, другие пользователи не видят записи, которые были в ней созданы.

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

Последний раз редактировалось kaakaa, 04.09.2014 в 12:56.
Ответить с цитированием
Этот пользователь сказал Спасибо за это полезное сообщение:
Uniq! (08.09.2014)
  #40  
Старый 08.09.2014, 13:02
Аватар для Uniq!
Uniq! Uniq! вне форума
Местный
 
Регистрация: 29.09.2010
Сообщения: 539
Версия Delphi: Delphi XE3
Репутация: 374
По умолчанию

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  
Старый 08.09.2014, 13:11
kaakaa
 
Сообщения: n/a
По умолчанию

Смотри TForm.OnCloseQuery.
В этом обработчике ты определяешь, были сделаны изменения в данных или нет.

Классика обработки:
1) Пользователь закрывает форму (нажимает кнопку закрыть и т.п.);
2) Диалог сохранения данных;
3) Пользователь не хочет сохранять данные, тогда ROLLBACK;
4) Пользователь хочет сохранять данные, тогда проверка и если все ОК, то COMMIT.

Последний раз редактировалось kaakaa, 08.09.2014 в 13:23.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 23:52.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter