FAQ - Вопросы - ответы - советы - Базы данных
Вопрос:
Как научить VCL делать REFRESH для запросов правильно? Особенно интересует REFRESH для связки MASTER-DETAIL.
Ответ:
Старо как мир, и нет ничего военного:
PROCEDURE REFRESHQUERY (QUERY : TQUERY; F : BOOLEAN);
VAR B : TBOOKMARK;
BEGIN
WITH QUERY DO
IF QUERY.ACTIVE THEN
BEGIN
B:=GETBOOKMARK;
TRY
CLOSE;
UNPREPARE; {Если не поставить этого, то если используется SELECT
SP, то иногда последующая операция вешает сервер.
Кто скажет почему?!}
ACTIVE:=TRUE;
IF F THEN BEGIN
TRY
GOTOBOOKMARK(B)
EXCEPT
ON EDATABASEERROR DO FIRST;
END
END
ELSE FIRST;
FINALLY
FREEBOOKMARK(B);
END;
END;
END;
Уфф! Кажется, лучше уже не сделать. :)
DBTABLES можно опционально пропатчить (см.в конце), чтобы иметь такой вот рулезный 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 DO
FOR I := 0 TO FIELDCOUNT - 1 DO
RESULT := RESULT + FIELDS[I].FIELDNAME + ';';
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 DO
WITH TFIELD(FIELDS[I]) DO
IF CALCULATED OR LOOKUP THEN FIELDS.DELETE(I);
CANLOCATE := FIELDS.COUNT > 0;
IF CANLOCATE THEN
BEGIN
IF FIELDS.COUNT = 1 THEN
KEYVALUES := TFIELD(FIELDS[0]).VALUE
ELSE BEGIN
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 DO
BEGIN
KEYNAMES := KEYNAMES + ';' + TFIELD(FIELDS[I]).FIELDNAME;
KEYVALUES[I] := TFIELD(FIELDS[I]).VALUE;
END;
END;
FINALLY
FIELDS.FREE;
END;
WITH QUERY DO
BEGIN
BMK := NIL;
DISABLECONTROLS;
TRY
BOOKMARKFOUND := FALSE;
IF BOOKMARKSEARCH THEN
BMK := GETBOOKMARK;
CLOSE;
OPEN;
IF ASSIGNED(BMK) THEN
TRY
GOTOBOOKMARK(BMK);
BOOKMARKFOUND := TRUE;
EXCEPT END;
IF NOT 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;
TRY
IF FDATALINK.DATASOURCE NIL THEN
BEGIN
DATASET := FDATALINK.DATASOURCE.DATASET;
IF DATASET NIL THEN
IF DATASET.ACTIVE AND (DATASET.STATE DSSETKEY) THEN
DOREFRESHQUERY(SELF, GETFIELDNAMESSTR(SELF), FALSE);
END;
FINALLY
ENABLECONTROLS;
END;
END;
