Чтение онлайн

ЖАНРЫ

Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil

Востриков С М

Шрифт:

Данный способ работы с array-полями нельзя применять в режиме CachedUpdates.

Второй способ работы с array-полями позволяет использовать их в "живых" запросах и редактировать при помощи стандартных визуальных компонентов (рис. 2.62).

Рассмотрим запросы, указанные в свойствах ArrayDataSet:

SelectSQL:

SELECT

JOB.JOB_CODE,

JOB.JOB_GRADE,

JOB.JOB_COUNTRY,

JOB.JOB_TITLE,

JOB.LANGUAGE_REQ[1] LQ1,

JOB.LANGUAGE_REQ[2] LQ2

FROM

JOB JOB

ORDER BY 1,2,3

Рис 2.62.

Внешний вид формы примера DemoArrayS. Второй вариант использования array-полей

UpdateSQL:

UPDATE JOB SET

JOB_TITLE = -?JOB_TITLE,

JOB JOB_GRADE=?JOB_GRADE,

JOB.JOB_COUNTRY=?JOB_COUNTRY,

LANGUAGE_REQ = ''LQ

WHERE

JOB_CODE = ?OLD_JOB_CODE

and JOB_GRADE = ?OLD_JOB_GRADE

and JOB_COUNTRY = ?OLD_JOB_COUNTRY

InsertSQL:

INSERT INTO JOB(

JOB_CODE,

JOB_GRADE,

JOB_COUNTRY,

JOB_TITLE,

LANGUAGE_REQ

)

VALUES(

?JOB_CODE,

?JOB_GRADE,

?JOB_COUNTRY,

?JOB_TITLE,

?LQ

)

DeleteSQL:

DELETE FROM JOB

WHERE

JOB_CODE = ?OLD_JOB_CODE

and JOB_GRADE = ?OLD_JOB_GRADE

and JOB_COUNTRY = ?OLD_JOB_COUNTRY

RefieshSQL:

SELECT

JOB.JOB_CODE,

JOB.JOB_GRADE,

JOB.JOB_COUNTRY,

JOB.JOB_TITLE,

JOB.LANGUAGE_REQ[1] LQ1,

JOB.LANGUAGE_REQ[2] LQ2

FROM

JOB JOB

WHERE

(

JOB.JOB_CODE = ?OLD_JOB_CODE

and JOB. JOB_GRADE = ?OLD_JOB_GRADE

and JOB.JOB_COUNTRY = ?OLD_JOB_COUNTRY

)

На этот раз мы выбираем только два элемента из нашего поля-массива. Обратите внимание' несмотря на то что в выбирающем запросе мы явным образом выделяем два элемента массива, а в модифицирующих запросах мы обновляем поле целиком На самом деле, это, конечно, не совсем так, однако данный синтаксис наиболее удобен и близок к естественному SQL-запросу несмотря на то что во внутренней реализации FIBPlus использует специальные функции работы с массивами Обратим внимание на компонент QryAirField TpFIBUpdateObject. Именно он позволит нам правильно сформировать значение параметра "LQ" в модифицирующих запросах Разумеется, для этой цели вполне бы подошел и простой TpFIBQuery, однако удобство TpFIBUpdateObject заключается в первую очередь в том, что он выполняет запрос автоматически и сам подставляет туда нужные значения параметров в зависимости от значений TpFIBDataSet. Вот запрос, который выполняет QryArrField SELECT

JOB LANGUAGE_REQ,

JOB JOB_CODE

FROM

JOB JOB

WHERE

JOB JOB_CODE=?OLD_JOB_CODE and

JOB.JOB_GRADE=?OLD_JOB_GRADE and

JOB.JOB_COUNTRY=?OLD_JOB_COUNTRY

Обратим внимание на свойства QryArrField (рис 2 63)

Рис 2.63. Свойство компонента QryArrField

Обработчик QiyAnField AtteiExecute

procedure TForm2 QryArrFieldAfterExecute(Sender: TObject);

var v Variant,

begin

v = QryArrField Fields[0] GetArrayValues,

with ArrayDataSet do begin

v[l] = FieldByName('LQ1') AsString,

v[2] = FieldByName( LQ2 ) AsString,

QryArrField Fields[0] SetArrayValue(v);

QUpdate Params ByName[ LQ ] AsQuad :=

QryArrField.Fields[0] AsQuad;

end;

QryArrField Close;

end;

Теперь все становится совершенно очевидным Поскотьку свойство QiyAnField KindUpdate равно ukModify, то QiyArrField выполняет запрос при изменении записи в AnayDataSet а поскольку свойство QiyArrField ExecuteOider равно eoBeforeDefault, то запрос (QiyArrField SQL) выполняется до того, как AirayDataSet выполнит свой собственный UpdateSQL В обработчике QryArrField AfterExecute мы всего лишь получаем заново все

текущие элементы массива из базы данных, подменяем два из них новыми значениями, которые указал пользователь, и задаем значение параметра для ArrayDataSet.UpdateSQL Это означает что при выполнении ArrayDataSet.UpdateSQL формально будут обновлены все пять элементов массива но фактически изменены значения тотько двух элементов, которые изменил пользователь в TDBGrid.

Как видите работа с массивами достаточно проста поскотьку все основные сложности решают компоненты FIBPlus Хотелось бы также рассмотреть еще один специализированный компонент, входящий в FIBPlus Пример DemoArray демонстрирует работу с TDataSetContamei, использованным для синхронизации значений двух TpFIBDataSet, редактирующих наше апау-поле (рис 2 64)

Рис 2.64. Использование TDatabetContamer

Компонент DataSetContamerl помещен вместе с Database и Transaction на DataModule в нашем приложении Оба компонента AnayDataSet из разных форм нашего приложения ссылаются на DataSetContamerl при помощи свойства Contamei (рис 2 65)

Рис 2.65. Подключение компонентов TpFIBDataSet к DataSetContamerl

Компонент TDataSetContamei позволяет централизованно обрабатывать события от разных компонентов TpFIBDataSet, а также (расширяя, таким образом, список стандартных событий) посылать им сообщения, при получении которых они могут производить какие-то дополнительные действия. В нашем примере DataSetContainerl имеет обработчики двух событий OnDataSetEvent и OnUserEvent

procedure TDataModule2.DataSetsContainerlDataSetEvent(DataSet:

TDataSet;

Event: TKindDataSetEvent);

var Info: string;

begin

if Event = deAfterPost then

if DataSet.Owner.Name = 'Forml' then

DataSetsContainerl.NotifyDataSets(DataSet,

'Form2.ArrayDataSet', 'JOB_TABLE_CHANGED', Info)

else

if DataSet.Owner.Name = 'Form2' then

DataSetsContainerl.NotifyDataSets(DataSet,

'Form1.ArrayDataSet', 'JOB_TABLE_CHANGED', Info);

end;

procedure TDataModule2.DataSetsContainerlUserEvent(Sender:

TObject;

Receiver: TDataSet; const EventName: String; var Info:

String) ;

begin

if EventName = 'JOB_TABLE_CHANGED' then begin

with TpFIBDataSet(Sender) do

if (not CachedUpdates) and

(not TpFIBDataSet(Receiver).CachedUpdates) then

if

TpFIBDataSet(Receiver).Locate('JOB_CODE;JOB_GRADE;JOB_COUNTRY', varArrayOf([

FieldByNamet'JOB_CODE').AsString,

FieldByName('JOB_GRADE').AsString,

FieldByName('JOB_COUNTRY').AsString

]), []) then TpFIBDataSet(Receiver) Refresh

end;

end;

Смысл действий сводится к следующему: после изменения записи в одном из наших компонентов ArrayDataSet происходит событие AfterPost. Поскольку DataSetContainerl перехватывает все события у подчиненных компонентов, то срабатывает обработчик OnDataSetEvent. Параметр Event равен deAfterPost, а параметр DataSet ссылается на тот компонент, в котором произошло изменение записи. При помощи вызова метода NotifyDataSets DataSetContainerl посылает сообщение оставшемуся компоненту ArrayDataSet о том, что произошло изменение записи. Поскольку оба компонента на самом деле редактируют одну и ту же таблицу, то желательно синхронизировать изменения. Синхронизация происходит в обработчике события OnUserEvent, то есть при получении "извещения" об изменении какого-либо из ArrayDataSet.

Поделиться с друзьями: