Если вы чехол с компьютера снимаете чаще, чем платье с вашей подруги, то вы уже давно научный сотрудник.
Старо как мир, и нет ничего военного:
procedure RefreshQuery(Query: TQuery; F: boolean);
var
B: TBookMark;
beginwith Query doif Query.Active thenbegin
B := GetBookMark;
try
Close;
Unprepare;
{Если не поставить этого, то если используется select
SP, то иногда последующая операция вешает сервер.
Кто скажет почему?!}
Active := True;
if F thenbegintry
GotoBookMark(B)
excepton EDatabaseError do
First;
endendelse
First;
finally
FreeBookmark(B);
end;
end;
end;
Уфф! Кажется, лyчше yже не сделать. :)
dbtables можно опционально пpопатчить (см. в конце), чтобы иметь такой вот
pyлезный Detail query.
Update for dbtables.pas
New interface function DoRefreshQuery can Refresh TQuery component in
master-detail scheme and alone.
TQuery.RefreshParams should be updated
function GetFieldNamesStr(DataSet: TDataSet): string;
var
I: Integer;
begin
Result := '';
with DataSet dofor I := 0 to FieldCount - 1 dobegin
Result := Result + Fields[I].FieldName + ';';
end;
end;
procedure DoRefreshQuery(Query: TQuery; KeyFields: string; BookMarkSearch:
Boolean);
var
Fields: TList;
KeyValues: Variant;
KeyNames: string;
Bmk: TBookmark;
I: Integer;
BookmarkFound: Boolean;
CanLocate: Boolean;
begin
Fields := TList.Create;
if KeyFields = '' then
KeyFields := GetFieldNamesStr(Query);
try
Query.GetFieldList(Fields, KeyFields);
for I := Fields.Count - 1 downto 0 dowith TField(Fields[I]) doif Calculated or Lookup then
Fields.Delete(I);
CanLocate := Fields.Count > 0;
if CanLocate thenbeginif Fields.Count = 1 then
KeyValues := TField(Fields[0]).Value
elsebegin
KeyValues := VarArrayCreate([0, Fields.Count - 1], varVariant);
KeyValues[0] := TField(Fields[0]).Value;
end;
KeyNames := TField(Fields[0]).FieldName;
for I := 1 to Fields.Count - 1 dobegin
KeyNames := KeyNames + ';' + TField(Fields[I]).FieldName;
KeyValues[I] := TField(Fields[I]).Value;
end;
end;
finally
Fields.Free;
end;
with Query dobegin
Bmk := nil;
DisableControls;
try
BookmarkFound := False;
if BookMarkSearch then
Bmk := GetBookmark;
Close;
Open;
if Assigned(Bmk) thentry
GotoBookMark(Bmk);
BookmarkFound := True;
exceptend;
ifnot BookmarkFound and CanLocate then
Locate(KeyNames, KeyValues, []);
finally
EnableControls;
Screen.Cursor := crDefault;
FreeBookmark(Bmk);
end;
end;
end;
procedure TQuery.RefreshParams;
var
DataSet: TDataSet;
begin
DisableControls;
tryif FDataLink.DataSource <> nilthenbegin
DataSet := FDataLink.DataSource.DataSet;
if DataSet <> nilthenif DataSet.Active and (DataSet.State <> dsSetKey) then
DoRefreshQuery(Self, GetFieldNamesStr(Self), False);
end;
finally
EnableControls;
end;
end;
Here's the translation of the content into Russian:
Компонент VCL Delphi для обновления запросов!
Процедура RefreshQuery предназначена для обновления компонента TQuery, который может использоваться в схеме мастер-деталь. Цель - обеспечить правильное обновление запроса при изменении underlying данных.
Вот разбивка кода:
Метод GetBookMark получает текущий маркер для запроса.
Если запрос активен, то он закрывается и дезактивируется перед повторной открытией с помощью Active := True.
Если F истинно, то оно пытается вернуться к маркеру; если нет, то оно устанавливает первый запись как новый маркер.
Наконец, оно освобождает маркер.
Процедура DoRefreshQuery - более полная реализация обновления запроса. Она принимает три параметра:
Query: компонент TQuery для обновления.
KeyFields: строка, содержащая имена полей, используемых для поиска ключа.
BookMarkSearch: булевое значение, указывающее, нужно ли искать маркер перед обновлением.
Вот, что она делает:
Создает список полей из запроса и проверяет, есть ли среди них вычисляемые или просматриваемые; если да, то удаляет их из списка.
Если параметр KeyFields пуст, то он устанавливается в результат вызова GetFieldNamesStr для запроса.
Она пытается получить список полей для запроса с помощью GetFieldList.
Если количество полей больше 0, то она:
Создает массив variant для значений ключа
Заполняет массив значениями из полей в списке ключевых полей
Устанавливает CanLocate в true, если есть хотя бы одно поле в списке ключевых полей.
Она отключает контроли, закрывает и открывает запрос заново, а затем:
Если маркер найден, то она пытается вернуться к нему; если нет, то она ищет его с помощью ключевых полей.
Наконец, она включает контроли снова.
Процедура TQuery.RefreshParams вызывается при изменении источника данных или активации данных. Она проверяет, является ли данные активными и находится ли в состоянии, отличном от dsSetKey, а затем вызывает DoRefreshQuery.
В целом, этот код должен помочь обновлять компоненты TQuery правильно при изменении underlying данных.
В вашем комментарии "Уфф! Кажется, лyчше yже не сделать. :)" - я думаю, вы просто выражаете радость и облегчение, что наконец-то написали работающий процедуру обновления запроса!
В статье описывается способ научить VCL делать Refresh для запросов правильно, используя процедуры RefreshQuery и DoRefreshQuery.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.