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;