Блокировка данных объекта для редактирования из кода
Область применения: управляемое приложение, обычное приложение.
1.1. Прежде чем изменять существующий объект информационной базы из кода на встроенном языке, следует предварительно его заблокировать (установить «блокировку данных для редактирования» или «объектную блокировку»), тем самым, во-первых, убедиться, не заблокирован ли он другими объектами, во-вторых, попытаться предотвратить его изменение другими пользовательскими сеансами (или другими экземплярами объекта в этом же сеансе).
В противном случае, если при изменении и записи из встроенного языка не устанавливать блокировку объекта на время редактирования, то может возникнуть, например, ситуация, когда пользователь не сможет сохранить свои изменения, если эти же самые данные были конкурентно изменены в другом сеансе.
При этом блокировка данных для редактирования не запрещает запись заблокированных данных в других пользовательских сеансах (или в других экземплярах объекта в этом же сеансе), а лишь не позволяет нескольким объектам одновременно установить блокировку одних и тех же данных. В отличие от транзакционных блокировок данных, пессимистическая блокировка данных для редактирования предназначена для обеспечения конкурентной работы пользователей с объектами информационной базы 1С:Предприятия (элементами справочников, документами и т.д.) Подробнее о блокировке данных для редактирования см. документацию по платформе 1С:Предприятие 8 .
1.2. Для блокировки данных для редактирования из встроенного языка следует вызывать метод объектов Заблокировать или метод глобального контекста ЗаблокироватьДанныеДляРедактирования .
Пример № 1. Требуется заблокировать объект и, если это удалось, модифицировать данные. В противном случае – проинформировать пользователя об отказе в выполнении операции с помощью сообщения вида:
«Не удалось заблокировать запись. Действие (изменение, удаление или блокировка записи) не выполнено. Ошибка блокировки объекта. Объект уже заблокирован: компьютер: <имя компьютера>, пользователь: <имя пользователя>, сеанс: <номер сеанса>, начат: <дата и время>, приложение: <тип клиентского приложения>».
ФайлОбъект = ДанныеФайла.Ссылка.ПолучитьОбъект();
// Выполнить блокировку объекта от изменения другими режимами
// или пользователями; в случае блокировки —
// вывести пользователю сообщение об исключении.
ФайлОбъект.Заблокировать();
// Затем изменить и записать объект
ФайлОбъект.Редактирует = Справочники.Пользователи.ПустаяСсылка();
ФайлОбъект.Записать();
Аналогичным образом, можно воспользоваться методом глобального контекста ЗаблокироватьДанныеДляРедактирования :
ФайлОбъект = ДанныеФайла.Ссылка.ПолучитьОбъект();
// Выполнить блокировку объекта от изменения другими режимами
// или пользователями; в случае блокировки —
// вывести пользователю сообщение об исключении.
ЗаблокироватьДанныеДляРедактирования(ДанныеФайла.Ссылка);
// Затем изменить и записать объект
ФайлОбъект.Редактирует = Справочники.Пользователи.ПустаяСсылка();
ФайлОбъект.Записать();
Пример № 2. Требуется пропустить обработку объекта, если он заблокирован для редактирования. При очередном вызове процедуры (например, из фонового или регламентного задания) будет предпринята повторная попытка изменения объекта.
ФайлОбъект = ТекущаяВерсия.ПолучитьОбъект();
// Выполнить блокировку объекта от изменения другими режимами или пользователями.
УстановитьПолноеНаименование = Истина;
Попытка
ФайлОбъект.Заблокировать();
Исключение
// в случае блокировки — не выполнять изменение объекта
УстановитьПолноеНаименование = Ложь;
// записать предупреждение в журнал регистрации
ЗаписьЖурналаРегистрации(НСтр(«ru = ‘Фоновое обновление имен файлов'», Метаданные.ОсновнойЯзык.КодЯзыка),
УровеньЖурналаРегистрации.Предупреждение,, ФайлОбъект, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
// Пропустить обработку объекта, если он заблокирован.
Если УстановитьПолноеНаименование Тогда
ФайлОбъект.ПолноеНаименование = ПолноеНаименование;
ФайлОбъект.Записать();
КонецЕсли;
1.3. При редактировании данных в формах, платформа 1С:Предприятие автоматически устанавливает блокировку объекта, указанного в качестве основного реквизита формы.
2. Не следует проверять блокировку объектов для редактирования в следующих случаях:
Как заблокировать объект на изменение?
При программном изменении существующих объектов есть правило: сразу после получения объекта из ссылки, необходимо его заблокировать для редактирования. Это позволяет:
- во-первых, проверить, что данный объект не заблокирован в настоящий момент другим пользователем;
- во-вторых, гарантирует, что другой пользователь не сможет изменить объект, пока не будут записаны изменения в текущем сеансе;
Заблокировать произвольный объект можно двумя способами:
- Используя метод Заблокировать() объекта метаданных ссылочного типа (Справочники, Документы и т.п.);
- Используя метод ЗаблокироватьДанныеДляРедактирования() глобального контекста;
Давайте рассмотрим примеры работы с каждым из этих методов
Метод Заблокировать()
Если Ваш алгоритм не взаимодействует с пользователем, перед тем как заблокировать объект, следует проверить, не заблокирован ли этот объект другим пользователем или процессом. Если, все же, взаимодействует, следует исключить код для варианта 1. Тогда в случае заблокированного объекта будет вызвано исключение и пользователь увидит полное описание ошибки.
Недостатки: Метод доступен только в контексте сервера, толстого клиента или внешнего соединения
Метод ЗаблокироватьДанныеДляРедактирования()
Данный метод обладает большим спектром возможностей, чем предыдущий:
- он умеет блокировать записи регистра сведений;
- он умеет блокировать данные в контексте управляемых форм;
- он умеет блокировать данные, если совпадает версия данных;
С учетом этого, перепишем предыдущий пример следующим образом:
В том случае, когда нам необходимо заблокировать некоторые данные на время открытия управляемой формы, можно поступить следующим образом:
Блокировка будет снята неявно при закрытии привязанной формы, либо при завершении сеанса пользователя, либо явно при вызове метода РазблокироватьДанныеДляРедактирования()
1С заблокировать документ от изменения регламентным заданием, при открытии
Допустим имеется регламентное задание, которое раз в день меняет поле «Комментарий» в документе «Заказ покупателя». Регламентное задание должно пропускать открытые пользователями документы, чтобы не возникало ошибок.
Порядок действий:
- Добавить в форму документа заказа покупателя, при создании на сервере, следующий код:
Листинг 1 — модуль формы документа
- При открытии документа пользователь должен блокировать документ автоматически. Процедура по изменению реквизитов должна пропускать заблокированные документы. Программный код процедуры:
Листинг 2 — процедура запускаемая регламентным заданием
как заблокировать объект в УФ.
Есть несколько объектов справочники и документы.
У них только УФ.
Необходимо при открытии формы блокировать объект для того, чтобы в другом сеансе при невозможности заблокировать объект форма открывалась на просмотр.
Сделал в ПриЧтенииНаСервере
[1с]
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
Попытка
ТекущийОбъект.Заблокировать();
Исключение
ЭтаФорма.НеЗаблокирован = Истина;
КонецПопытки;
КонецПроцедуры
[/1с]
Где НеЗаблокирован это реквизит формы.
Но такой вариант не держит блокировку на время, пока форма открыта.
Как еще можно выкрутиться?
а теперь объясни
Выполняет блокировку объекта от изменения другими режимами или пользователями.
Сервер, толстый клиент, внешнее соединение.
Пример:
Попытка
Объект.Заблокировать();
Исключение
Текст = «ru = «»Не удалось заблокировать объект»»;»
+ » en = «»Can’t lock the object»»»;
Предупреждение(НСтр(Текст) » «»» + Объект + «»»!
|»+ ОписаниеОшибки());
КонецПопытки;
да почитай там сп, Гилевых — просветись и напомни мне как там и чо, просто все стесняються завить, что профаны в этом вопросе — я нет, требую знаний
ИДИ КОПАЙ и взахлеб опиши решение, иначе я предам тебя анафеме!
(5)
там только два режима:
Исключительный (Exclusive)
Разделяемый (Shared)
Исключаемый мне не подходит, так как не смогут отрывать во втором сеансе на просмотр
Разделяемая не подходит, так как во втором сеансе она без проблем на разделяемую наложится
Можно ли прочитать есть разделяемые блокировки или нет?
Вариант накладывать исключающую и при положительном исходе снимать и накладывать разделяемую смущает, что есть разрыв.
Или можно у разделяемой блокировки на ходу менять режим?
Сделала такую блокировку:
[1с]
ТаблицаИсточникой = Новый ТаблицаЗначений;
ТаблицаИсточникой.Колонки.Добавить(«Ссылка»);
НоваяСтрока = ТаблицаИсточникой.Добавить();
НоваяСтрока.Ссылка = ТекущийОбъект.Ссылка;
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить(«Справочник._НаселенныеПункты»);
ЭлементБлокировки.УстановитьЗначение(«Ссылка», ТекущийОбъект.Ссылка);
ЭлементБлокировки.ИсточникДанных = ТаблицаИсточникой;
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных(«Ссылка», «Ссылка»);
Не пойму почему поля блокировки двумя строками http://screencast.com/t/eoirO4gTZanh, а не одной
(14)
— У меня две базы, между которыми идет обмен каждые N минут.
— В обоих базах одни и те же элементы справочника могут менять между обменами и получится, что на момент обмена один и тот же элемент изменился в двух базах.
— Для разрешения этой ситуации я в обоих базах сделал регистр захваченных объектов.
— В случае отсутствия в нем записи о конкретном элементе справочника, я понимаю, что последний раз элемент редактировался не здесь и через ВебСервис проверяю регистрацию этого элемента в плане обмена во второй базе. В случае отсутствия изменений я во второй базе в регистре убираю захват, а в первой записываю захват. Если это удалось, то форма открывается в режиме редактирования, если захватить не удалось то форма открывается на чтение.
Все это нормально запустилось.
Но может быть ситуация, когда объект во второй базе открыли в форме. изменять не начали и ответственно объект еще не заблокировался, В плане обмена регистрации нет и первая база будет думать, что можно редактировать.
Вот мне и нужно при открытии формы сразу блокировать объект
(16)>>либо во второй перехватить событие (которого нет) о том, что в форме начинают редактировать объект,
Зато есть свойство Модифицированность оно истина когда что то изменили на форме но еще не записали
Еще придумал такой вариант.
Во второй базе В форма обработчик ожидания каждые 15 сек проверяет не модифицирована ли форма. Если произошел переход с немодифицированный на модифицированную, то проверить не захвачен ли он первой базой. Если захвачен, то предупредить пользователя, что его изменения (сделанные в течении 15 минут) не сохранятся.
Думаю на этом и остановлюсь.
(26)Не проверяю я локально, регистр в обоих базах.
Если из первой захватывают объект второй. то по Вебсервису во второй меняется регистр захвата.
А в обработчике ожидания я проверяю локальный регистр и то, по сути 1 раз при смене немодифицирваон на модифицирован
ЗаблокироватьДанныеДляРедактирования (LockDataForEdit)
Синтаксис:
ЗаблокироватьДанныеДляРедактирования(<Ключ>, <ВерсияДанных>, <ИдентификаторФормы>)
Параметры:
Тип: Любая ссылка на объект информационной базы; РегистрСведенийКлючЗаписи.<Имя регистра сведений>.
Ссылка на объект, который должен быть заблокирован, или ключ записи независимого регистра сведений, которая должна быть заблокирована.
<ВерсияДанных> (необязательный)
Тип: Строка.
Версия блокируемого объекта в формате Base64. Используется, если параметр <Ключ> имеет тип Любая ссылка на объект информационной базы.
Если указан, то при блокировке объекта проверяется версия объекта базы данных. При несовпадении версии или отсутствии объекта в базе данных генерируется исключение.
Значение по умолчанию: Неопределено.
<ИдентификаторФормы> (необязательный)
Тип: УникальныйИдентификатор.
Уникальный идентификатор формы. Если параметр указан, то блокировка устанавливается на все время жизни формы и может быть снята:
методом РазблокироватьДанныеДляРедактирования с тем же идентификатором формы;
при закрытии формы;
при завершении сеанса.
Если параметр не указан, то блокировка устанавливается на ограниченное время и может быть снята:
с помощью метода РазблокироватьДанныеДляРедактирования без указания идентификатора формы;
при окончании транзакции, если блокировка установлена в транзакции;
при окончании работы встроенного языка (для режимов запуска «Тонкий клиент» и «Веб-клиент»; при возврате управления с сервера);
при завершении сеанса.
Значение по умолчанию: Неопределено.
Описание:
Заблокировать данные для редактирования в управляемой форме.
Вызывает исключение, если объект уже заблокирован, в том числе и методом Заблокировать.