Использование блокировок Назад В начало Вперед

Для корректного разрешения конфликтов пользователей при доступе к одному и тому же информационному ресурсу на модификацию используется блокировка отдельных записей таблицы, однозначно идентифицирующей этот информационный ресурс (например BaseDoc для счета). Режим автоблокировки описывается декларативно для тех интерфейсов в которых он необходим. Обычно это все интерфейсы, где происходит модификация записей.

<Раздел описания блокировок> ::=
  (lock <список таблиц> | all) by <имя таблицы>
<список таблиц> ::= <имя таблицы> {"," <имя таблицы>}

Этот раздел может присутствовать в интерфейсе после описания главной логической таблицы этого интерфейса и его параметров. Список таблиц после ключевого слова lock это те таблицы, модификации которых будут запрещены если не прошла блокировка таблицы, которая указана после ключевого слова by. Если после ключевого слова lock указано ключевое слово all вместо списка таблиц то будут блокироваться все области ввода интерфейса.

Сама блокировка происходит в момент попытки пользователя модифицировать одно из полей областей ввода, корневые таблицы которых участвуют в режиме блокировки. В случае если запись удалось заблокировать пользователь работает как ни в чем не бывало, в противном случае он получает сообщение что другой пользователь уже модифицирует эту запись. Для отслеживания пользователей, ушедших пить чай и не вернувшихся и т.д. существует механизм TimeOut'а. По окончании определенного периода времени редактирования записи в случае отсутствия к.л. действий пользователя происходит автоматическое разблокирование записей и откат изменений функцией RereadRecord. Время TimeOut'а задается в параметрах. Другим параметром задается время за которое до времени разблокировки начинать предупреждать об этом пользователя, предупреждение пользователя производится с помощью визуализации.

При описании режима автоблокировки в VIP указывается таблица которая однозначно идентифицирует информационный ресурс (далее головная таблица) и список таблиц модификацию которых необходимо запрещать в случае если не прошла блокировка головной таблицы. При этом надо иметь в виду что запрещается не модификация самих таблиц (update из обработчика к.л. события вызвать можно) а модификация пользователем полей, находящихся в областях ввода с корневыми таблицами из этого  списка. При необходимости проверки в обработчике событий интерфейса состояния блокировки (заблокированы ли области ввода, связанные с какой либо таблицей) можно воспользоваться функцией IsProtected(tnИмяТаблицы) т.к. блокировка происходит через стандартный механизм ProtectRecord. Естественно, запись автоматически разблокируется при сходе с записи.

Для использования автоблокировок в прикладном коде необходимо в первую очередь определить головные таблицы, которые идентифицировали бы информационные ресурсы требующие конкурентного доступа. Например, для платежных поручений это будет таблица PlPor. В интерфейсе прямого редактирования таблицы оборотов желательно сделать головной тоже таблицу PlPor для того, чтобы не было возможности одновременно менять, например, платежное поручение и обороты к нему из другого интерфейса. После определения головных таблиц необходимо расставить описанную выше конструкцию в тех режимах где это необходимо. Большим плюсом конструкции lock all by является то, что она не влияет на логику прикладной обработки (кроме случаев нажатия кнопок на записи, которую не удалось заблокировать - в таких случаях желательно сделать проверку на IsProtected в обработчиках соответствующих событий).

Для управления режимом автоблокировки во время выполнения программы используются параметры конфигурационного файла:

Пример

В данном примере через систему автоблокировок производится защита от изменений областей ввода для таблиц сотрудников и разноски сотрудников по проектам. При этом реально блокируются записи только в таблице сотрудников. В случае если блокировка сотрудника не прошла, редактирование полей и вызов события cmPick в области ввода с корневой таблицей empproj производится не будут.

interface EditSotr;
  create view as
	select * from employee, projects, empproj
	where (( employee.nrec	== empproj.cemployee and
			 empproj.cproject == project.nrec ));
  parameters employee.nrec;

  lock all by employee;

  browse EmpBrowse
	table Employee;
	show at (,,,10);
	fields
	Employee.Name
  end;
 
  browse EmpProjBrowse
	table empproj
	show at (,11);
	fields
	Project.Name
  end;

  tableEvent table Employee
	cmUpdateRecord : update current employee;
	cmInsertRecord : insert current employee;
	cmDeleteRecord : delete current employee;
  end;

  TableEvent table EmpProj
	cmUpdateRecord : update current empproj;
	cmInsertRecord : insert current empproj;
	cmDeleteRecord : delete current empproj;
	cmPick		 : RunInterface(GetProject,EmpProj.cProject);
  end;
end.