На этот раз мы выбираем только два элемента из нашего поля-массива. Обратите внимание' несмотря на то что в выбирающем запросе мы явным образом выделяем два элемента массива, а в модифицирующих запросах мы обновляем поле целиком На самом деле, это, конечно, не совсем так, однако данный синтаксис наиболее удобен и близок к естественному 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;