Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil
Шрифт:
Именно такой механизм и реализуется в BDE, когда мы вынуждены целиком переоткрывать все запросы. В IBX без этого легко можно обойтись, используя RefieshSQL, значительно сэкономив при этом сетевой трафик и снизив нагрузку на сервер, поскольку получение всего лишь одной измененной записи гораздо более эффективно, чем переоткрытие запроса целиком.
IBX предоставляет нам возможность быстро сгенерировать необходимые модифицирующие запросы при помощи редактора IBDataSet (рис 2.9.)
Выбрав из списка Table Name нашу таблицу и нажав кнопку Get Table Fields мы сформируем списки Key Fields и Update Fields. В списке Key Fields нужно выделить те поля, которые будут формировать
Рис 2.9. Генератор модифицирующих запросов
В списке Update Fields необходимо выделить те поля, которые потом пользователь сможет редактировать. На рисунке видно, что поле FULL_NAME не включено в список, поскольку это CALCULATED-поле и его значение нельзя менять
К сожалению, надо самому точно знать, какие поля необходимо исключать из модифицирующих запросов поскольку компоненты не дадут ни одной подсказки. Даже при подготовке данного раздела пришлось потратив впустую некоторое время, чтобы понять, почему IBDataSetl никак не "хотел" становиться модифицируемым. Только выяснив, что поле FULL_NAME является вычислимым, стало понятно, почему возникает ошибка IBDataSetl пытался выполнить команду Prepare для каждого из запросов и сервер каждый раз сообщал, что не может изменить read-only-поле! Хочется отметить, что этой проблемы нет в генераторе запросов, реализованном в FIBPlus.
Остается нажать кнопку Generate SQL, чтобы получить все запросы flnsertSQL, ModifySQL, DeleteSQL и RefreshSQL.
Программное редактирование данных
Как показал некоторый опыт в поддержке пользователей, программисты, впервые применяющие IBX и аналогичные компоненты, не совсем понимают каким образом можно использовать TIBDataSet для того, чтобы управлять данными программно, а не просто давать пользователю возможность вносить какието исправления.
Например, периодически возникает вопрос: "А как мне автоматически вставить новую запись в IBDataSet? Может быть, стоит разместить рядом отдельный компонент IBSQL, в котором написать запрос INSERT, выполнить его, а потом переоткрыть IBDataSet? Или, может быть, можно синхронизировать новую запись в IBSQL и существующие записи в IBDataSet? Существуют ли методы для прямого редактирования локального буфера записей в IBDataSet?"
Подобные "технологические" решения можно придумывать очень долго: поскольку фантазия разработчиков практически неистощима, мы можем найти выход из любой ситуации и обойти любое ограничение существующей технологии. Однако в данном случае решения "проблемы" проистекают от простого непонимания принципов работы IBDataSet. Поверьте, все гораздо проще.
В самом начале главы сказано, что TIBDataSet порожден классом TDataSet, а значит, наследует основные принципы его работы. У TIBDataSet как наследника TDataSet существует три основных метода для изменения данных: Delete, Insert (Append) и Edit.
Предположим, что мы хотим вставить новую запись в наш IBDataSetl по нажатии кнопки:
procedure TForml.ButtonlClick(Sender: TObject);
begin
with IBDataSetl do begin
Insert;
FieldByName('EMP_NO').Aslnteger := 147;
FieldByName('DEPT_NO').Aslnteger := 600;
FieldByName('JOB_CODE').AsString := 'VP';
FieldByName('JOB_GRADE') .Aslnteger : = 2 ;
FieldByName('SALARY').Aslnteger := 105900;
FieldByName('HIRE_DATE').AsDateTime := Now;
FieldByName('JOB_COUNTRY').AsString := 'USA';
FieldByName('FIRST_NAME').AsString := 'Иван';
FieldByName('LAST_NAME').AsString := 'Иванов';
Post;
end;
end;
Теперь
Если запрос выполнился успешно, то IBDataSetl автоматически выполняет RefreshSQL для обновления только что вставленной записи - для проверки изменений, внесенных на стороне базы данных.
Аналогичным образом мы можем редактировать записи. Например, мы можем модифицировать все записи в нашем запросе:
procedure TForml.ButtonlClick(Sender: TObject);
begin
with IBDataSetl do begin
First;
while not Eof do begin
Edit;
FieldByName('LAST_NAME').AsString :=
trim(FieldByName('LAST_NAME').AsString) + ', esquire;
Post;
Next ;
end;
end;
end;
Принцип тот же самый, что и при вставке записей. Мы вызываем метод Edit, подготавливая буфер текущей записи для редактирования, потом меняем значения поля при помощи FieldByName, а потом заканчиваем редактирование, вызвав метод Post. В результате IBDataSetl подставляет значения полей записи в ModifySQL и выполняет запрос.
Оговоримся, что в реальной практике подобная обработка большого множества записей не является хорошим решением. Гораздо легче было бы выполнить одну команду UPDATE, которая добавила бы строку ', esquire' ко всем записям таблицы. Пример выше дан только для демонстрации метода Edit.
Как видно из примеров выше, нет никакой нужды ни в каких дополнительных компонентах, синхронизации о прочих непонятных "телодвижениях", если мы хотим редактировать данные в IBDataSet программно.
И снова про транзакции
Новичков иногда пугает "особенность" IBX закрывать все запросы при подтверждении или "откате" транзакции. Разместим на нашей форме две кнопки, как показано на рис. 2.10: Button 1 (свойство Caption равно Commit) и Button2 (Rollback).
Рис 2.10. Кнопки управления транзакцией
Далее напишем следующие обработчики событий нажатия на эти кнопки:
procedure TForml.ButtonlClick(Sender: TObject);
begin
IBTransactionl.Commit;
end;
procedure TForml.Button2Click(Sender: TObject);
begin
IBTransactionl.Rollback;
end;
Теперь если мы запустим приложение и нажмем любую из этих кнопок, то увидим, что после завершения транзакции наш запрос также будет закрыт.