Кеширование TSQLQuery - как отключить?

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

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

Кеширование TSQLQuery - как отключить?

Сообщение Nick74 » 15.03.2017 14:16:14

Подскажите пожалуйста как с ним (TSQLQuery) нормально работать с кешем или как его (кеш) отключить? Что-то я после Delphi слегка в шоке.

Поясню - есть форма с полями DBEdit. Хочу при изменении полей пользователем показывать кнопку Сохранить, а при сохранении убирать ее.
В Delphi это делалось в одном месте в TDataSource.OnChangeState, а-ля Button.Visible = Query.State = dsEdit; тут не получается, так как запись сохраняется в кеш, а применяется уже потом, а ошибку у меня выдает база данных.
Хорошо, делаю показ кнопки в TDataSource.OnChangeState, в TSQLQuery.OnAfterPost пишу Query.ApplyUpdates; Button.Visible := false;
Вроде работает, если не прошло сохранение, кнопка остается активной, но вот беда - теперь при ошибке Query в состоянии dsBrowse, повторное нажатие сохранения ничего не сохраняет (А очень хочется получить ту же ошибку повторно) и надо датасет вручную переключать в dsEdit (и я так понимаю слабая гарантия, что он остался на нужной записи) и что он вообще что-то будет сохранять, так как формально ничего не изменилось в записи б), то есть еще и желательно все поля пометить как измененные). Геморрой.

Вот как это делать правильно и проще, подскажите плиз? Пока пользы в кеше не вижу, зато вижу один вред.
Nick74
новенький
 
Сообщения: 25
Зарегистрирован: 15.03.2017 13:55:06
Откуда: Москва

Re: Кеширование TSQLQuery - как отключить?

Сообщение Nick74 » 28.03.2017 15:57:52

Неужто никто не пользуется TSQLQuery & Firebird? (
Попробую переформулировать: триггер базы данных (Firebird) не дает обновлять данные, если что-то в них ошибочно.
При этом в интерфейсе я хочу, чтобы человек не смог уйти с ошибочной записи (И даже не смог ее сохранить!) пока не исправит ошибку. Как это можно сделать?
Nick74
новенький
 
Сообщения: 25
Зарегистрирован: 15.03.2017 13:55:06
Откуда: Москва

Re: Кеширование TSQLQuery - как отключить?

Сообщение Лекс Айрин » 28.03.2017 21:17:26

Nick74,А можно ли изменять размер кеша? Тогда его можно попытаться сделать равным нулю (или, для самых умных, 1). Это наверняка вызовет необходимость его отключения. Или игнор. Вообще, можно посмотреть исходники и поискать есть ли подобный функционал в наличии.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Кеширование TSQLQuery - как отключить?

Сообщение Nick74 » 29.03.2017 11:01:26

Лекс Айрин
Сомнительно, нигде не видел размера кеша. Да и по коду ясно, что так не решишь.
Покопался в исходниках, нашел нужное место.
Как видно, TCustomSQLQuery.Post сначала вызывает TDataSet.Post, а только затем применяет ApplyUpdates (В режиме AutoApplyUpdates).
Внутри TDataSet.Post также видно, что идет запись в кеш, смена позиции курсора, изменение статуса датасета, и только после этого AfterPost.
При этом, я так понимаю, операции с БД выполняются в ApplyUpdates и откатить операцию ну никак не могут.

Блиииин, как я привык к ошибкам, возвращаемым SQL-базой ((( Неужели никто этим не пользуется? Пошел копаться в сторонних компонентах...
Код: Выделить всё
procedure TCustomSQLQuery.Post;
begin
  inherited Post;
  If (sqoAutoApplyUpdates in Options) then
    ApplyUpdates;
end; 

procedure TDataSet.Post;
begin
  UpdateRecord;
  if State in [dsEdit,dsInsert] then
    begin
    DataEvent(deCheckBrowseMode,0);
    DoBeforePost;
    If Not TryDoing(@InternalPost,OnPostError) then exit;  // <-- Тут запись в кеш
    cursorposchanged;
    FreeFieldBuffers;
    SetState(dsBrowse);
    Resync([]);
    DoAfterPost;                                                              // <-- Тут можно вызвать ApplyUpdates вручную, только поздно уже. Статус датасета изменен, курсор сдвинут и все такое
    end
  else if State<>dsSetKey then
    DatabaseErrorFmt(SNotEditing, [Name], Self);
end;   
Nick74
новенький
 
Сообщения: 25
Зарегистрирован: 15.03.2017 13:55:06
Откуда: Москва

Re: Кеширование TSQLQuery - как отключить?

Сообщение alexs » 29.03.2017 11:04:27

Попробуй ZEOS - может поможет.
А вообще - почему элементарную проверку допустимости вводимых данных не сделать на морде приложения? Зачем допускать ошибочные данные до сервера?
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Кеширование TSQLQuery - как отключить?

Сообщение Nick74 » 29.03.2017 12:56:45

alexs
Если недопустимость данных - больше нуля или не пустое или в списке ('A','B'), то возможно.
А если недопустимость зависит от других таблиц? Скажем вы вводите операцию расхода в бухгалтерии, а программа должна проверить не превышают ли введенные данные наличную сумму на счету, что, естественно, хранится в другой таблице или таблицах. Ну не будете же вы на стороне клиента делать запросы к трем другим таблицам?
А если недопустимо повтор записи? То есть стоит уникальный индекс в базе данных? Что тогда?
Хотя я привык почти все делать в БД (Триггерах или структуре) независимо от проверки со стороны клиента. Допустим, какое-то поле в БД меняется с NULL на NOT NULL, а в программе я забыл в описании поля указать Required.
С TSQLQuery получается "замечательно" - запись сохранилась, и только потом по сути асинхронно где-то там ругнулось "Ой, апдейт то не прошел". А Датасет уже тю-тю, dsBrowse блин, да и запись может быть уже не та активная.
Пойду посмотрю ZEOS, спасибо за подсказку.
Nick74
новенький
 
Сообщения: 25
Зарегистрирован: 15.03.2017 13:55:06
Откуда: Москва

Re: Кеширование TSQLQuery - как отключить?

Сообщение pupsik » 29.03.2017 13:19:05

Nick74 передавайте привет транзакциям... Или они уже не могут делать "откат"?

а программа должна проверить не превышают ли введенные данные наличную сумму на счету, что, естественно, хранится в другой таблице или таблицах.
программа? А я, почему то считал что это делается на стороне сервера. И программа как бы ничего и не должна.
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

LQuery

Сообщение Nick74 » 29.03.2017 16:54:45

pupsik
Под "Откатом" я имел ввиду откат состояния датасета и грида, то бишь чтобы они вернулись в режим редактирования. Откатывать в базе данных ничего не надо, так как операция редактирования прервана триггером/нарушением уникальности индекса.
По поводу "Программы" - я имел ввиду функционал, который программа должна выполнять. И как раз и ругался на то, что логика на сервере не может прервать POST кешированного датасета.
То есть: есть редактируемый TDBEdit (TDBGrid, неважно) с неким полем из таблицы БД, на которой на сервере уникальный индекс.
При редактировании этой колонки и нажатии "Сохранить" в TSQLQuery корректно происходит POST, смена состояния на dsBrowse, возможно смещение на следующую запись (В случае грида), и только потом происходит ApplyUpdates, который получает ошибку нарушения индекса. Логичное действие при этом в интерфейсе - не давать уходить с сохраняемой записи, пока не будет введено допустимое значение поля.
Для этого мне надо вручную: найти нужную запись в гриде (Мы ведь ушли с сохраненной, скажем стрелочкой), переместиться к ней, перейти в режим редактирования, возможно еще "изменить" ранее редактировавшиеся поля (в противном случае повторный Post, подозреваю, ничего не сохранит - впрочем не проверял, но допускаю, что работает именно так). Все это не нужно было бы, если бы не работало кеширование изменений.

Добавлено спустя 7 минут 43 секунды:
Re: Кеширование TSQLQuery - как отключить?
Посмотрел другие компоненты. Проблемы с кешированием больше нет нигде. Пока в процессе выбора.
UIB - нет совместимого с TDataSource редактируемого элемента. То бишь редактируемый грид не делается?
IBX - глюки с UTF8 даже в design режиме.
Zeos - пока тестирую..
Nick74
новенький
 
Сообщения: 25
Зарегистрирован: 15.03.2017 13:55:06
Откуда: Москва

Re: Кеширование TSQLQuery - как отключить?

Сообщение olegy123 » 29.03.2017 18:12:38

Упс..

Добавлено спустя 1 час 7 минут 33 секунды:
Nick74 писал(а):Поясню - есть форма с полями DBEdit. Хочу при изменении полей пользователем показывать кнопку Сохранить, а при сохранении убирать ее.

Я делал в Action1.Enabled:=Query.State in [dsEdit,dsInsert];

Добавлено спустя 10 минут 23 секунды:
А если попробывать так?
SQLQuery1.DisableControls;
.. сохраняем..
SQLQuery1.EnableControls;
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Кеширование TSQLQuery - как отключить?

Сообщение alexs » 29.03.2017 22:22:52

Nick74 писал(а):UIB - нет совместимого с TDataSource редактируемого элемента. То бишь редактируемый грид не делается?

Для него надо взять мой FBDataSet. Автор не стал развивать свой из за него.

Nick74 писал(а):Zeos - пока тестирую..

Хороший комбайн. Но для птицы там нет полного контроля над транзакциями.
Сам им пользуюсь для всего, кроме птицы.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: LQuery

Сообщение *Rik* » 29.03.2017 23:36:01

Nick74 писал(а):IBX - глюки с UTF8 даже в design режиме.

Какие IBX смотрел?
Аватара пользователя
*Rik*
постоялец
 
Сообщения: 426
Зарегистрирован: 19.04.2011 12:18:51
Откуда: Урал

Re: Кеширование TSQLQuery - как отключить?

Сообщение Nick74 » 30.03.2017 10:42:58

olegy123 писал(а):Я делал в Action1.Enabled:=Query.State in [dsEdit,dsInsert];
А если попробывать так?
SQLQuery1.DisableControls;
.. сохраняем..
SQLQuery1.EnableControls;

А смысл? Состояние и текущую запись теряет именно датасет, контролы то тут при чем? Даже если и получится, потеряется возможность редактирования в гриде в Excel стиле - не будут работать кнопки перемещения между записями.

*Rik* писал(а):Какие IBX смотрел?

ibx4lazarus 2.0.2 с сайта MWA. При установке Character set UTF8 выдает Division by zero даже при попытке заполнить поля датасета.

alexs писал(а):Для него надо взять мой FBDataSet. Автор не стал развивать свой из за него.

Сейчас попробую. В принципе UIB мне понравился, удобный...

alexs писал(а):Хороший комбайн. Но для птицы там нет полного контроля над транзакциями.
Сам им пользуюсь для всего, кроме птицы.

Ну не сказать что мне оно сильно нужно, в основном планируется однопользовательский режим из-за Embedded FB.
Nick74
новенький
 
Сообщения: 25
Зарегистрирован: 15.03.2017 13:55:06
Откуда: Москва

Re: Кеширование TSQLQuery - как отключить?

Сообщение *Rik* » 30.03.2017 11:32:16

Nick74 писал(а):
*Rik* писал(а):Какие IBX смотрел?

ibx4lazarus 2.0.2 с сайта MWA. При установке Character set UTF8 выдает Division by zero даже при попытке заполнить поля датасета.

http://visual-t.ru/ibexpress.html
Аватара пользователя
*Rik*
постоялец
 
Сообщения: 426
Зарегистрирован: 19.04.2011 12:18:51
Откуда: Урал

Re: Кеширование TSQLQuery - как отключить?

Сообщение Nick74 » 30.03.2017 13:24:58

*Rik* писал(а):http://visual-t.ru/ibexpress.html

Попробовал. Разместил датасет, транзакцию, базу, грид. Почему то не находит fbclient.dll, ладно, указываю ручками.
Открывается норм. Меняю любое поле, при сохранении ошибка "SIGSEGV файл runtimeIBCustomDataSet.pas строка 3828 PRecordsData(Buffer)^.rdBookmarkFlag := bfBof", Buffer=nil...
ЧЯДНТ?

Добавлено спустя 26 минут 55 секунд:
Дальнейшие эксперименты:

ZEOS
Не знает pfRefreshOnInsert и как следствие не использует конструкцию returning KEYFIELD, поэтому единственный работающий метод для INSERT - создавать TZSequence объект и указывать ему правильный номер генератора (Который вытаскивается из RDB$RELATION_FIELDS, так как в Firebird3 при использовании конструкции AUTOGENERATE BY DEFAULT имя генератора неизвестно.) В принципе можно написать автоматическое создание такого объекта, хотя руки чешутся поправить ЗЕОС.

UIB + FBDataset
Открывает, редактирует нормально, но при возникновении ошибки от БД и повторной попытке что-то сохранить начинает ругаться на закрытый запрос и далее из ступора не выходит. Подозреваю что-то не так с режимами транзакций, победить не смог.

Задумался, это у меня руки кривые или запросы слишком большие? )))
Неужто никто не использует Firebird с редактированием и вставкой новых строк в гриде? Хмм.
Nick74
новенький
 
Сообщения: 25
Зарегистрирован: 15.03.2017 13:55:06
Откуда: Москва

Re: Кеширование TSQLQuery - как отключить?

Сообщение *Rik* » 30.03.2017 14:07:07

Nick74 писал(а):
*Rik* писал(а):http://visual-t.ru/ibexpress.html

Попробовал. Разместил датасет, транзакцию, базу, грид. Почему то не находит fbclient.dll, ладно, указываю ручками.
Открывается норм. Меняю любое поле, при сохранении ошибка "SIGSEGV файл runtimeIBCustomDataSet.pas строка 3828 PRecordsData(Buffer)^.rdBookmarkFlag := bfBof", Buffer=nil...
ЧЯДНТ?

Добавлено спустя 26 минут 55 секунд:
Дальнейшие эксперименты:

ZEOS
Не знает pfRefreshOnInsert и как следствие не использует конструкцию returning KEYFIELD, поэтому единственный работающий метод для INSERT - создавать TZSequence объект и указывать ему правильный номер генератора (Который вытаскивается из RDB$RELATION_FIELDS, так как в Firebird3 при использовании конструкции AUTOGENERATE BY DEFAULT имя генератора неизвестно.) В принципе можно написать автоматическое создание такого объекта, хотя руки чешутся поправить ЗЕОС.

UIB + FBDataset
Открывает, редактирует нормально, но при возникновении ошибки от БД и повторной попытке что-то сохранить начинает ругаться на закрытый запрос и далее из ступора не выходит. Подозреваю что-то не так с режимами транзакций, победить не смог.

Задумался, это у меня руки кривые или запросы слишком большие? )))
Неужто никто не использует Firebird с редактированием и вставкой новых строк в гриде? Хмм.

Скорее всего у тебя что-то с руками не так.. У меня целая контора на ibx сидит, приложение масштаба предприятия, работает с 2мя базами на FireBird > 50гб, уже несколько лет полет нормальный, редактируют по разному и в гриде и без. Сделаю тебе тестовое приложение. Какая версия FireBird?
Аватара пользователя
*Rik*
постоялец
 
Сообщения: 426
Зарегистрирован: 19.04.2011 12:18:51
Откуда: Урал

След.

Вернуться в Lazarus

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

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

Рейтинг@Mail.ru