Почему в 1С не блокируется документ при открытии в управляемых формах и как это исправить?

Программист 1С v8.3 (Управляемые формы)
← На главную

Разберем достаточно распространенную ситуацию при разработке на платформе 1С:Предприятие с использованием управляемых форм. Проблема заключается в том, что при открытии документа он не блокируется от изменений другими пользователями. В результате разные пользователи могут одновременно открыть один и тот же документ, отредактировать его и записать, тем самым затерев данные друг друга. Выясним причину такого поведения и рассмотрим подробнее, как правильно реализовать механизм блокировки.

Анализ ошибочного подхода

Проанализируем типичный пример кода, который разработчики иногда помещают в обработчик ПриСозданииНаСервере в надежде заблокировать документ:


Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
    Попытка
        Объект.Ссылка.ПолучитьОбъект().Заблокировать();
    Исключение
        ШаблонСообщения = НСтр("ru = 'Документ редактируется другим пользователем.%1%2'");
        ТекстСообщения  = СтрШаблон(ШаблонСообщения, Символы.ПС, ОписаниеОшибки());
        ВызватьИсключение ТекстСообщения;
    КонецПопытки;
    
    ЗаблокироватьДанныеФормыДляРедактирования();
КонецЕсли;

Посмотрим, что происходит в этом коде на самом деле и почему блокировка пропадает сразу после открытия формы.

  1. Временный экземпляр объекта: Основная ошибка кроется в конструкции Объект.Ссылка.ПолучитьОбъект().Заблокировать(). В управляемой форме реквизит Объект имеет тип ДанныеФормыСтруктура, а не ДокументОбъект. Вызывая ПолучитьОбъект(), мы создаем в оперативной памяти сервера совершенно новый, отдельный экземпляр объекта документа.
  2. Сборка мусора: Мы успешно накладываем блокировку на этот временный экземпляр. Однако, как только выполнение процедуры ПриСозданииНаСервере завершается, платформа очищает память. Временный объект уничтожается сборщиком мусора, и, как следствие, установленная на него пессимистическая блокировка автоматически снимается. Для пользователя форма открывается, но реальный объект в базе данных остается свободным.

Как правильно блокировать данные формы

Для управляемых форм платформой предусмотрен специальный метод: ЗаблокироватьДанныеФормыДляРедактирования(). Рассмотрим его особенности.

Этот метод не просто пытается установить блокировку, он возвращает булево значение. Если возвращается Истина, значит данные успешно заблокированы текущим сеансом. Если Ложь — объект уже заблокирован кем-то другим. В ошибочном коде выше результат выполнения этого метода просто игнорировался.

Блокировка, установленная этим методом, привязывается к расширению формы и сохраняется до тех пор, пока форма не будет закрыта, либо пока мы принудительно не вызовем метод РазблокироватьДанныеФормыДляРедактирования().

Правильная реализация блокировки

Разберем по шагам, как нужно переписать логику блокировки. Наиболее подходящим местом для таких проверок является обработчик ПриЧтенииНаСервере, так как он вызывается каждый раз при перечитывании данных из базы данных в форму.


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    
    // Пытаемся заблокировать данные формы
    Если Не ЗаблокироватьДанныеФормыДляРедактирования() Тогда
        // Если блокировка не удалась, запрещаем редактирование
        ЭтаФорма.ТолькоПросмотр = Истина;
        
        // Можно дополнительно сообщить пользователю
        Сообщить("Документ открыт в режиме просмотра, так как редактируется другим пользователем.");
    КонецЕсли;

КонецПроцедуры

Используя этот подход, мы гарантируем, что если другой пользователь уже занял объект, текущий пользователь увидит форму только для чтения и не сможет внести конфликтующие изменения.

Дополнительные причины проблем с блокировками

Если код написан правильно, но "некоторые документы" всё равно иногда не блокируются или ведут себя странно, проанализируем дополнительные факторы:

  1. Режим управления блокировками: Проверьте свойства конфигурации и самого документа. Если в конфигурации установлен режим "Автоматический и управляемый", а у документа — только "Управляемый", стандартное поведение пессимистических блокировок может отличаться.
  2. Фоновые задания: Если в момент открытия формы над документом выполняется какая-то операция в фоновом задании (например, проведение или рассылка), это задание может удерживать транзакционную блокировку. Это иногда приводит к конфликтам с попыткой наложить объектную блокировку.
  3. Использование Библиотеки Стандартных Подсистем (БСП): Если вы используете типовую или самописную конфигурацию с внедренной БСП, обратите внимание на общий модуль РаботаСДиалогамиСервер. Часто в БСП применяется программный механизм через регистры сведений (например, запись информации о том, кто и когда открыл объект). Это позволяет не только блокировать документ, но и выводить пользователю информативное сообщение с указанием ФИО коллеги, который сейчас работает с документом.

Подводя итог, откажитесь от использования ПолучитьОбъект() для целей блокировки в контексте формы. Опирайтесь на метод ЗаблокироватьДанныеФормыДляРедактирования(), обязательно проверяйте результат его выполнения и управляйте свойством ТолькоПросмотр. Это обеспечит стабильную работу системы и защитит данные от одновременной перезаписи.

← На главную