lazarus = Firebird - транзакции

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

lazarus = Firebird - транзакции

Сообщение bpg » 12.04.2018 11:27:01

Lazarus 1.8.2 , FireBird 2.5 Механизм доступа к данным SQLdb, подключение Remote TCP/IP, настроен alias.conf
Подскажите, как правильно работать с сетевой БД, первый такой проект у меня, до этого были только локальные БД.
Сейчас подключение с разных компьютеров по сети работает, данные видятся, но только не обновляются, если я на одной машине делаю допустим изменение личной карточки человека, то на другой машине это не увидится до тех пора пока не зайдешь и не выйдешь из программы.
Понимаю, что необходим механизм или транзакций или правильной работы с методами post, applyupdate и т.д.
bpg
новенький
 
Сообщения: 36
Зарегистрирован: 28.11.2017 21:23:18

Re: lazarus = Firebird - транзакции

Сообщение Vadim » 12.04.2018 12:19:53

bpg
Если сильно не заморачиваться и если у Вас на клиенте всего пара-тройка наборов данных, то можно по таймеру делать, к примеру, каждые 5 минут SQLQuery.Refresh, тогда в SQLQuery будут обновляться данные с сервера.
Vadim
долгожитель
 
Сообщения: 3022
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: lazarus = Firebird - транзакции

Сообщение bpg » 12.04.2018 13:09:20

Правильно я понимаю, что при формировании любого запроса и при посте записей, мне в начало и в конец процедуры надо вставить SQLTransaction1.StartTransaction;
SQLTransaction1.Commit;
и все?
bpg
новенький
 
Сообщения: 36
Зарегистрирован: 28.11.2017 21:23:18

Re: lazarus = Firebird - транзакции

Сообщение Vadim » 12.04.2018 14:38:53

bpg
Сначала Вам нужно определиться, что Вы подразумеваете под словосочетанием "не обновляются".
Начало и конец транзакции касаются только сервера. Если Вы даёте команду "Начать транзакцию" (StartTransaction), то на сервере БД создаётся что-то вроде специальной временной таблицы, куда заносятся отправленные Вами на сервер данные. В рабочую таблицу они будут перемещены только тогда, когда Вы дадите команду "Подтверждение транзакции" (Commit).
Если же Вы имеете в виду, что получив некий набор данных в клиентский компонент SQLQuery, Вы ожидаете, что полученные сервером данные будут автоматом переправляться в этот клиентский набор данных, то транзакции здесь даже и рядом не валялись. Для этого случая необходимо либо обрабатывать события сервера, одно из которых, в частности, получение им новых данных, либо Вы вручную обновляете свой клиентский набор данных способом, который я Вам привёл выше.
Вам крайне необходимо определиться с употребляемой Вами терминологией, иначе получение Вами ответа на Вашу проблему может затянуться на неопределённо долгий срок в силу того, что те, кто читает Ваши посты не могут понять, что именно вы имели в виду. ;-)
Vadim
долгожитель
 
Сообщения: 3022
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: lazarus = Firebird - транзакции

Сообщение bpg » 12.04.2018 16:04:44

Спасибо за ответы. Проясняется в голове.
Проблема с SQLQuery.Refresh в следующем. У меня есть blob поле, я туда кидаю картинку, после этого чтобы увиделась эта картинка в другой вкладке делаю Post. После ApplyUpdates и Refresh.
Только вот засада, в самой программе на стороне клиента все ок, картинка появляется на другой вкладке, а вот на другом подключении к БД, хоть бы даже через IBExpert пока принудительно не обновишь подключение, ничего не помогает. Пришлось в программе делать Connection.close, потом Connection.Active. Разве это правильно?

P.S. Не могу понять как в 1С бухи сидят и каждый делает свою накладную? и видят если она сохранилась? Они там при каждом сохранении рефрешат все данные? Это не сильно долго? Работает же быстро ...
bpg
новенький
 
Сообщения: 36
Зарегистрирован: 28.11.2017 21:23:18

Re: lazarus = Firebird - транзакции

Сообщение Lucifer » 12.04.2018 16:43:02

Используй EVENT. Сервер при завершении транзакции генерирует событие. На клиенте создаешь подписки на эти события и ревфрешишь тот датасет, на который прилетело изменение.
Lucifer
новенький
 
Сообщения: 31
Зарегистрирован: 05.01.2014 21:39:03
Откуда: Новороссийск

Re: lazarus = Firebird - транзакции

Сообщение Vadim » 12.04.2018 16:56:20

bpg писал(а):P.S. Не могу понять как в 1С бухи сидят и каждый делает свою накладную? и видят если она сохранилась? Они там при каждом сохранении рефрешат все данные? Это не сильно долго? Работает же быстро ...

Откровенно говоря - понятия не имею. Последний раз я работал с 1С ещё в конце прошлого века, когда она была версии 7.7. :-D

bpg писал(а):Только вот засада, в самой программе на стороне клиента все ок, картинка появляется на другой вкладке, а вот на другом подключении к БД, хоть бы даже через IBExpert пока принудительно не обновишь подключение, ничего не помогает.

Вот это уже ближе к теме. ;-)
Post и ApplyUpdate управляют локальным кэшем данных на стороне клиента. Эти штуки остались ещё со времён локальных таблиц. У Вас, вполне возможно неправильно настроено подтверждение транзакции. Хотя может быть и не неправильно, тем не менее автоматического подтверждения не происходит, следовательно сервер хранит полученные данные у себя во временной таблице. Разрыв связи с клиентом означает, что на самом сервере происходит автоматическое подтверждение транзакции.
Давайте посмотрим настройки компонента SQLTransaction. У него есть свойство Action, которое заведует подтверждением или отменой транзакций в автоматическом режиме. По умолчанию оно имеет значение caRollback, т.е. отмена транзакции. Если выставить значение в caCommit, то сразу же как только Вы вносите какие-либо данные в свой локальный набор данных (SQLQuery) и после того, как Вы передвигаетесь на новую строку данных, происходит автоматическое подтверждение транзакции для сервера. Этот режим превосходно подходит, когда изменений\дополнений данных немного. если же изменений\дополнений бешеное количество, то лучше всего применить ручное управление транзакциями.
Например, Вам нужно добавить в какую-то таблицу 50 000 записей. В режиме подтверждения транзакции для каждой записи, можно будет себе ногти до локтей изгрызть, пока дождёшся окончания вставки. :-) В этом случае свойство Action лучше поставить в caNone (т.е. ничего не делать), а перед началом вставки написать SQLTransaction.StartTransaction, а после окончания всех вставок написать SQLTransaction.Commit.
Vadim
долгожитель
 
Сообщения: 3022
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: lazarus = Firebird - транзакции

Сообщение olegy123 » 12.04.2018 17:26:06

bpg писал(а):Проблема с SQLQuery.Refresh в следующем. У меня есть blob поле, я туда кидаю картинку, после этого чтобы увиделась эта картинка в другой вкладке делаю Post. После ApplyUpdates и Refresh.

FB очень любит работать с транзакциями, точнее без них FB вообще не работает.. их там 4 вида. http://www.ibase.ru/ibtrans/

В компонентах есть подключение транзакций.. они есть как на SQLConnection так и на SQLQuery. Разные компоненты выстраивают их работу по своему, одни требуют явного подхода, у других - эмулируют ODBC - типа что клиент не должен парится...
Отсюда различное поведение в SQLConnection - следовательно вся работа будет сводится в 1 транзакцию от подключения до отключения.. подходить для ReadOnly режима. Клиенту нужно только позырить на таблицы и отвалить..
Для SQLQuery - более тонкая работа.. там даже два запроса могут друг у друга не видеть, хотя сидеть на одном SQLConnection. Отсюда нужно знать когда один SQLQuery получает данные а второй SQLQuery эти же данные обновляет.. и их, если есть необходимость синхронизировать..

Добавлено спустя 4 минуты 54 секунды:
Lucifer писал(а):Используй EVENT.

класная вещь!!! За что мне нравится FB. Но он не спасает от транзакций.. Просто дает сигнал на что то..

Нигде нет кроме PostgreSQL, но там его нужно реализовывать через ..опу.
olegy123
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 25.02.2016 12:10:20

Re: lazarus = Firebird - транзакции

Сообщение bpg » 12.04.2018 17:41:12

Lucifer писал(а):Используй EVENT. Серв


olegy123 писал(а):класная вещь!!! За что мне нравится FB. Но он не спасает от транзакций.. Просто дает сигнал на что то..


Подскажите где почитать про eventы , по моему это выход для меня, на http://wiki.freepascal.org/TFBEventMonitor маловато, и не очень понял.
Спасибо , что помогаете
bpg
новенький
 
Сообщения: 36
Зарегистрирован: 28.11.2017 21:23:18

Re: lazarus = Firebird - транзакции

Сообщение olegy123 » 12.04.2018 17:43:56

bpg писал(а):P.S. Не могу понять как в 1С бухи сидят и каждый делает свою накладную? и видят если она сохранилась? Они там при каждом сохранении рефрешат все данные? Это не сильно долго? Работает же быстро ...

в 7.7 да, там даже таймеры сидят которые рефрешат.. в 8ке наверное также..

тебе нужно разобратся с уровнем транзакции в FB. Там есть такой который позволяет в рамках открытой транзакции видить новые данные без закрытия самой транзакции..
FB это инкрементальная БД, т.е. там все в виде тайм-шифта, или снапшота происходит.. т.е. открываешь транзакцию видишь только те данные которые были совершены до открытия этой транзакции.. до завершения транзакции данные как бы находятся вне базы.. другие не видят их, если не находятся в транзакции видимости новых не подтвержденных данных.. и до Commit их как бы нет.

Добавлено спустя 32 минуты 9 секунд:
bpg писал(а):Подскажите где почитать про eventы , по моему это выход для меня, на http://wiki.freepascal.org/TFBEventMonitor маловато, и не очень понял.
Спасибо , что помогаете
У всех компонент (в том числе в ZeosDBO) практически все одинаково, RegisterEvents/UnRegisterEvents - это библиотечная dll функция. на С++/Java/C# будет одинаково работать.


Код: Выделить всё
  EventsM:=TFBEventMonitor.create(Self);  // [b]создаем объект для получения событий от FB[/b]
  EventsM.Connection:=IBConnection1;  //  [b]подключаем к IBConnection1[/b]
  ///EventsM.Events.CommaText:='"E1",E2,E3,E4,"E5","E6","E7"'; //quotes are ignored ???// [b]афтор жжот.[/b]
  EventsM.Events.add('Event1'); // [b]добавим что хотим получить это событие[/b]
  EventsM.Events.add('Event2');  //[b] добавим что хотим получить это событие[/b]
...
  EventsM.Events.add('Event_new_row_TableXXXX'); //  [b]и такое событие[/b]

  EventsM.OnEventAlert:=OnFBEvent; // [b]обработчк сообщений от FB[/b]
..
  EventsM.RegisterEvents;   // [b]регистрация всех ожидаемых событий от FB,  IBConnection1 должен быть уже подключен(!!!!!) к базе FB, так как регистрация происходит в БД, а не на клиенте.. т.е. клиент может и не получать всех событий от базы, а тех на которые хочет быть подписан этим он сообщает через регистрацию в подключенной БД.[/b]


  EventsM.UnRegisterEvents;  // [b]базе FB сообщаем что не хотим принимать события[/b]
...

procedure TForm1.OnFBEvent(Sender: TObject; EventName: string;
  EventCount: longint; var CancelAlerts: boolean);
begin
  Memo1.Lines.Add(EventName+' occurred '+IntToStr(EventCount)+' times.');  .. -- >[b] выведет событие.. EventName="Event_new_row_TableXXXX"[/b]
end;


Где то в базе FirebirdSQL
http://wm-help.net/lib/b/book/4054355128/740
Код: Выделить всё
CREATE TRIGGER POST_NEW_ORDER FOR SALES ACTIVE AFTER INSERT POSITION 0
AS
BEGIN
POST_EVENT 'new_order'; END ^
SET TERM ; ^
Оператор POST EVENT доступен и в триггерах, и в хранимых процедурах.

POST_EVENT 'Event_new_row_TableXXXX'; // должен вызвать у клиента в OnFBEvent EventName="Event_new_row_TableXXXX"
иные сообщения(не входящие в список) к клиенту не будут посылаться самой БД. т.е. POST_EVENT 'new_order' не будет послан этому клиенту.
olegy123
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 25.02.2016 12:10:20

Re: lazarus = Firebird - транзакции

Сообщение bpg » 12.04.2018 18:34:26

Спасибо.
olegy123 писал(а):// афтор жжот.
ь меня это и смущало, не мог въехать, это что? такие константы официальные или зарезервированные символы. ;-)

Добавлено спустя 20 часов 39 минут 2 секунды:
Что то я совсем туплю. Целый день бьюсь, не работает. Ругается на
Код: Выделить всё
  EventsM.OnEventAlert:= OnFBEvent; // [b]обработчк сообщений от FB[/b]

Ошибка
1. mainunit.pas(1427,26) Error: Wrong number of parameters specified for call to "OnFBEvent"
2. mainunit.pas(502,1) Error: Found declaration: OnFBEvent(TObject;AnsiString;LongInt;var Boolean);

В основной форме в событие при активации
Код: Выделить всё
  {Отлавливаем EVENT от сервера}
  EventsM:=TFBEventMonitor.create(Self);  // создаем объект для получения событий от FB
  EventsM.Connection:=DM.IBConnection1;  //  подключаем к IBConnection1
  EventsM.Events.add('db_connect'); // добавим событие подключения к БД[/b]
  EventsM.Events.add('data_post'); //  событие обновления данных[/b]
  EventsM.OnEventAlert:= OnFBEvent; // обработчк сообщений от FB
  EventsM.RegisterEvents;   // регистрация всех ожидаемых событий от FB

В конец вставил procedure OnFBEvent(Sender: TObject; EventName: string; EventCount: longint; var CancelAlerts: boolean);

Сама процедура
Код: Выделить всё
procedure TMainForm.OnFBEvent(Sender: TObject; EventName: string;
  EventCount: longint; var CancelAlerts: boolean);
begin
ShowMessage(EventName);
Memo1.Lines.Add(EventName+' occurred '+IntToStr(EventCount)+' times.');
end;
bpg
новенький
 
Сообщения: 36
Зарегистрирован: 28.11.2017 21:23:18

Re: lazarus = Firebird - транзакции

Сообщение Lucifer » 13.04.2018 17:44:01

EventsM.OnEventAlert:= OnFBEvent; // обработчк сообщений от FB
заменить на EventsM.OnEventAlert:= @OnFBEvent; // обработчк сообщений от FB
Lucifer
новенький
 
Сообщения: 31
Зарегистрирован: 05.01.2014 21:39:03
Откуда: Новороссийск

Re: lazarus = Firebird - транзакции

Сообщение bpg » 13.04.2018 21:24:12

не помогло, я это пробовал, из этой информации https://stackoverflow.com/questions/319 ... pascal-laz
Lucifer писал(а): EventsM.OnEventAlert:= @OnFBEvent;

та же ошибка
bpg
новенький
 
Сообщения: 36
Зарегистрирован: 28.11.2017 21:23:18

Re: lazarus = Firebird - транзакции

Сообщение Снег Север » 14.04.2018 07:51:18

Ошибка говорит о несоответствии параметров вашей процедуры и OnEventAlert.
Аватара пользователя
Снег Север
энтузиаст
 
Сообщения: 1358
Зарегистрирован: 27.11.2007 16:14:47

Re: lazarus = Firebird - транзакции

Сообщение bpg » 14.04.2018 12:19:53

Подскажите где ошибка?
В главной форме приложения в type
Код: Выделить всё
    procedure ToolButtonSetupClick(Sender: TObject);
    procedure OnFBEvent(Sender: TObject; EventName: string; EventCount: longint; var CancelAlerts: boolean);  /// <------- отлов событий
  private
  public
  end;
var
  MainForm: TMainForm;     
......
TimeStart: DWORD;
  EventsM : TFBEventMonitor;

implementation
{$R *.lfm}                           

в процедуре OnActivate
Код: Выделить всё
  {Отлавливаем EVENT от сервера} //UPD_PEOPLE data_post db_connect
  EventsM:=TFBEventMonitor.create(Self);  // создаем объект для получения событий от FB
  EventsM.Connection:=DM.IBConnection1;  //  подключаем к IBConnection1
  EventsM.Events.add('db_connect'); // добавим событие подключения к БД[/b]
  EventsM.Events.add('data_post'); //  событие обновления данных[/b]
  EventsM.Events.add('UPD_PEOPLE'); //  событие обновления данных[/b]
  EventsM.OnEventAlert:= @OnFBEvent; // обработчк сообщений от FB
  EventsM.RegisterEvents;   // регистрация всех ожидаемых событий от FB

На кнопке Закрыть программу
Код: Выделить всё
  EventsM.UnRegisterEvents;   // отписка от регистрации всех ожидаемых событий от FB

Сама процедура:
Код: Выделить всё
procedure TMainForm.OnFBEvent(Sender: TObject; EventName: string;
  EventCount: longint; var CancelAlerts: boolean);
begin
ShowMessage(EventName);
StatusBar1.Panels[3].Text:= 'EVENTS: '+ EventName;
//Memo1.Lines.Add(EventName+' occurred '+IntToStr(EventCount)+' times.');
end;

События отлавливаются, но при закрытии программы вываливается External SIGSEGV.

Если поместить процедуру отлова событий из OnActivate в OnCreate то SIGSEGV с явным указанием на EventsM.Connection:=DM.IBConnection1; // подключаем к IBConnection1
Замучался уже. Третий день.
bpg
новенький
 
Сообщения: 36
Зарегистрирован: 28.11.2017 21:23:18

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru