Многопользовательская работа в трехзвенных информационных системах
Отметим, что организация многопользовательской работы в трехзвенных системах с CORBA-сервером практически не отличается от организации многопользовательской работы в системах с COM-серверами. В обоих случаях при коллизиях следует создавать обработчик события OnReconcileError компонента TClientDataSet.
Рассмотрим часто встречающийся при многопользовательской работе случай, когда два пользователя пытаются отредактировать одну и ту же запись. При работе с сетевыми версиями настольных СУБД и при работе с серверными СУБД в такой ситуации обычно используется блокировка записи (или нескольких записей, занимающих общую единицу хранения информации, называемую страницей), не позволяющая пользователю редактировать запись, уже редактируемую другим пользователем, пока последний ее не освободит.
В случае трехзвенной системы механизм блокировок, используемый в традиционной двухзвенной модели "клиент/сервер", может оказаться неприемлемым, так как при использовании briefcase model промежуток времени между редактированием записи и сохранением ее в базе данных может быть весьма длительным. Поэтому организация многопользовательской работы в трехзвенных системах отличается от привычной.
При попытке сохранения сервером приложений измененной записи в базе данных производится поиск изменяемой записи либо по ключевому полю, либо по всем полям в зависимости от значения свойства UpdateMode ответственного за этот процесс компонента TDBDataSet на сервере приложений и сравнение всех полей изменяемой записи с исходными значениями (т.е. теми, которые были в кэше клиента на момент получения этой записи с сервера до того, как пользователь изменил в кэше эту запись). Если какие-либо поля за время между получением оригинала записи клиентом и попыткой сохранить изменения были модифицированы другим пользователем, запись может быть передана обратно в клиентское приложение для дальнейшей обработки пользователем
Так как данные, предоставляемые компонентом TClientDataSet, представляют собой содержимое кэша, вполне возможно, что несколько пользователей создадут свои локальные копии исходных записей, полученных с сервера баз данных, и каждый начнет их редактировать.
Предположим, два пользователя отредактировали одну и ту же запись и пытаются сохранить ее на сервере. В этом случае тот из пользователей, кто пытался первым сохранить в базе данных свой вариант отредактированной записи, сумеет это сделать, тогда как второй пользователь должен быть уведомлен об ошибке, связанной с тем, что сохраняемая им запись уже изменена другим пользователем.
Для обработки подобных ошибок существует событие OnReconcileError компонента TClientDataSet, возникающее в случае, когда при попытке сохранения измененной записи в базе данных выясняется, что запись была изменена другим пользователем. Пример такой обработки можно найти в репозитарии объектов..
Откроем проект клиентского приложения, созданного ранее. Далее на странице страницы Dialogs репозитория объектов выберем пиктограмму Reconcile Error Dialog. В результате к проекту будет добавлена диалоговая панель следующего вида (рис. 11):
Рис. 11. Reconcile Error Dialog из репозитария объектов.
Далее включим ссылку на модуль вновь созданного диалога в секцию uses модуля, связанного с главной формой проекта. Следует также перенести вновь созданную диалоговую панель в список Available Forms на странице Forms диалоговой панели опций проекта. В противном случае этот диалог будет появляться при запуске приложения.
Затем создадим обработчик события OnReconcileError компонента ClientDataSet1:
procedure TForm1.ClientDataSet1ReconcileError(DataSet: TClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction); begin Action := HandleReconcileError(DataSet, UpdateKind, E);
end;
Отметим, что в модуле, связанной с вновь созданным диалогом, уже содержится функция HandleReconcileError, ссылка на которую содержится в обработчике событий.
Скомпилируем и сохраним проект, а затем запустим две копии созданного приложения. В каждой из копий приложения внесем разные изменения в одно и то же поле одной и той же записи и попытаемся сохранить изменения в базе данных. При этом первое изменение с успехом сохранится, а в результате попытки внести второе изменение появится вновь созданная диалоговая панель (рис. 12):
Рис. 12. Сообщение о конфликте, получаемое пользователем при попытке сохранения измененных данных.
В таблице в нижней части формы содержатся значения полей, вызвавшие коллизию: значение, которое данный пользователь пытается сохранить в базе данных, и исходное значение поля, сгруженное в кэш при открытии TClientDataSet. Пользователь может пропустить эту запись, оказаться от внесения своей версии значения поля в базу данных, переписать его поверх старого значения.
Отметим, что обработка коллизий, возникших при редактировании detail-записей, производится точно так же.
Если по-каким-либо причинам обработка коллизий при многопользовательской работе должна быть отличной от предложенной, можно отредактировать имеющийся код (и при необходимости саму диалоговую панель).
<< | | >>