Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil
Шрифт:
Тем не менее если вы не хотите, чтобы подтверждение транзакции вызывало закрытие всех активных TpFIBDataSet, то вы можете использовать метод CommitRetaining. Этот метод подтверждает транзакцию и автоматически запускает новую с теми же самыми параметрами, не закрывая при этом пользовательских курсоров (запросов, выбирающих данные)
Данный метод содержал ошибку реализации, поэтому не рекомендуется слишком часто вызывать CommitRetaining для версий Intel Base меньше чем 6.5.
То же самое касается и метода RollbackRetaining, который отменяет изменения, сделанные в контексте транзакции и запускает новую.
Данный метод появился в InteiBase версии 6.0.
Использование стандартных визуальных db-компонентов совместно с FIBPIus
Следующий
Рис 2.17. Подключение визуальных компонентов к TpFIBDataSet
Для этого нам необходимы два компонента. TpFIBDataSet HTpFTBTiansdction. TpFIBDataSet является потомком класса TDataSet и полностью совместим со всеми стандартными визуальными компонентами. Для связки TpFIBDataSet с визуальным компонентом CategoriesGrid (TDBGrid) компонент CategoriesDataSource подключен к CategoriesDataSet. TpFIBTransaction, как уже было сказано, предназначен для управления транзакцией.
Необходимо указать уровень изоляции транзакции при помощи свойства TPBMode, а также "подключить" CategoriesTransaction к pFIBDatabasel (2.18).
Рис 2.18. Подключение транзакции к компоненту pFIBDataBasel
Аналогично необходимо указать свойства Database и Transaction для компонента CategoriesDataSet (рис. 2.19).
Рис 2.19. Подключение компонента CategoriesDataSet к pFIBDataBasel и транзакции CategoriesTransaction
Теперь мы можем указать необходимые запросы к базе данных для получения и изменения данных в таблице Нужно написать запрос для получения данных, используя свойство SelectSQL. В нашем случае это будет очень простой запрос:
SELECT * FROM "Categories"
Теперь изменим немного код в процедуре:
procedure TMainForm.FormCreate(Sender: TObject);
begin
with TiniFile.Create('ib_price.ini') do begin
pFIBDatabasel.DBName := ReadString('Options', 'DBPath',
'C:\IBPRICE.GDB');
Free ;
end;
pFIBDatabasel.Open;
CategoriesDataSet.Open;
end;
В свойстве DataSet у компонента CategoriesSource (TDataSource) мы укажем CategoriesDataSet, а в свойстве DataSource у компонента CategoriesGrid (TDBGrid) укажем CategoriesSource. Теперь все данные, полученные в результате запроса, будут отображены в CategoriesGrid. Нам не нужно явным образом запускать транзакцию перед открытием запроса, поскольку по умолчанию свойство CategoriesDataSet.Options содержит ключ poStartTransaction и компонент сам запускает транзакцию После запуска приложения и открытия базы данных мы увидим следующий результат (рис. 2.20):
Рис 2.20. Вид запущенного приложения
Вместо CategoriesGrid мы могли использовать любой визуальный db-компонент, который используется в связке с TDataSource. Это мог быть TDBEdit, TDBLabel, TDBMemo и т. д., а также любые сторонние компоненты, которые придерживаются данного стандарта (TDBGridEh, например).
Как сделать запрос редактируемым? Автоматическая генерация модифицирующих запросов в design-time и run-time
Если вы попробуете исправить какие-то значения в CategoriesGrid,
то увидите, что в текущем состоянии мы имеем iead-only-запрос Для того чтобы наш запрос стал редактируемым, или "живым", нам надо написать несколько дополнительных запросов, которые будут автоматически выполнятся компонентом CategonesDataSet при редактировании данных в CategoriesGrid. Необходимо заполнить свойства (рис. 2.21).Рис 2.21. Свойства CategonesDataSet с запросами для чтения и модификации данных
FIBPlus включает специальный design-time-редактор для редактирования и генерации модифицирующих запросов. Вы можете вызвать "Generator SQLs" из контекстного меню, если нажмете правой кнопкой мыши на компоненте CategonesDataSet (рис. 2.22)
Для генерации модифицирующих запросов необходимо сначала указать основную таблицу в списке Если в запросе участвует только одна таблица, то она будет выбрана в списке автоматически После этого необходимо нажать кнопку Get Table Fields для заполнения списков "Key Fields" и "Update Fields '. В первом списке нужно выделить те поля, которые будут вставлены в условие WHERE во всех модифицирующих запросах. В списке "Update Fields" необходимо выделить те поля, которые мы хотим редактировать. По умолчанию выделены все поля таблицы "Categories" Теперь достаточно нажать кнопку Generate SQLs и получить автоматически все модифицирующие запросы, которые вы можете увидеть на закладке SQLs Например, мы получим следующий запрос для свойства InsertSQL
INSERT INTO "Categories"(
"Id" ,
" Name" ,
"GoodsCount"
)
VALUES(
:"Id",
:"Name",
:"GoodsCount"
)
Puc 2.22. Редактор компонента TpFIBDataSet, предназначенный для генерации модифицирующих запросов
Обратите внимание также на запрос для свойства RefreshSQL:
select * from "Categories"
WHERE
(
"Categories"."Id" = :"OLD_Id"
)
Это такой же выбирающий запрос, как и запрос в свойстве SelectSQL, но возвращать он должен только одну запись - текущую Теперь, после создания всех запросов, когда пользователь будет редактировать запись в CategoriesGrid, CategonesDataSet автоматически заполнит значения параметров : "Id", . "Name" и т д., теми значениями полей, которые наберет пользователь. После выполнения метода Post (который, в частности, вызывается при нажатии клавиши Enter в CategonesGnd) CategoriesDataSet выполнит соответствующий модифицирующий запрос После редактирования записи будет выполнен запрос из свойства UpdateSQL, при вставке новой записи - из InsertSQL, а при удалении записи - из DeleteSQL После выполнения любого модифицирующего запроса (кроме удаления) CategoriesDataSet автоматически выполняет запрос из RefreshSQL, подставляя в качестве условия текущие значения параметров. Это позволяет "узнать" значения всех полей текущей записи, если они были изменены при помощи триггеров базы данных.
Несколько слов о специальных префиксах для параметров, которые используются в FIBPlus.
Префикс "OLD_" фактически означает текущее значение одноименного поля или же предыдущее значение поля Термин "предыдущее значение" имеет смысл в запросе на удаление. Во всех остальных случаях, когда нужны актуальные значения полей, можно обходиться без данного префикса.
Префикс "NEW_" означает новое значение поля и фактически имеет смысл только в запросах на изменение и вставку. Однако новые значения полей в этих ситуациях также являются и текущими, а значит, префикс "NEW_" можно опускать