Почему при программном изменении документа возникает ошибка блокировки данных?

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

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

Понимание природы проблемы: прикладные vs оптимистические блокировки

Для начала важно разграничить два типа защиты данных, которые часто путают:

  1. Пессимистические (прикладные) блокировки: Это именно то, что вызывают ваши методы ЗаблокироватьДанныеДляРедактирования(). Они принудительно запрещают другим пользователям редактировать запись до момента завершения вашего алгоритма.
  2. Оптимистические блокировки (контроль версий): Это встроенный механизм платформы, который работает автоматически. Когда вы открываете форму документа, платформа запоминает версию данных в базе. Если в момент, когда форма открыта, данные в базе изменились (например, другим кодом), при попытке записи из формы платформа выдаст ошибку: «Данные были изменены или удалены». Она защищает вас от перезаписи чужих изменений «старой» версией.

Основная проблема в вашем случае заключается в том, что когда пользователь открывает форму «Заказа покупателя» и редактирует его, он создает в памяти клиента «образ» документа. Если параллельно ваш фоновый процесс (или вызов с сервера из «Заказа поставщику») пытается заблокировать и записать этот же объект, возникает конфликт версий.

Почему ошибка возникает именно при записи?

Рассмотрим сценарий возникновения конфликта по шагам:

  1. Пользователь открывает форму «Заказа покупателя». Платформа считывает версию данных (Версия_1).
  2. В этот момент вы проводите «Заказ поставщику». Ваш код успешно выполняет ЗаблокироватьДанныеДляРедактирования() и записывает изменения в «Заказ покупателя». Версия в базе меняется на (Версия_2).
  3. Пользователь в форме «Заказа покупателя» меняет что-то в реквизитах и нажимает «Записать».
  4. Платформа сравнивает версию из памяти формы (Версия_1) с версией в базе (Версия_2). Так как они не совпадают, платформа прерывает запись с ошибкой блокировки или сообщением о том, что данные были изменены другим пользователем.

Как решить проблему архитектурно?

Прямое изменение одних документов из других является не лучшей практикой разработки, так как это создает жесткие зависимости и блокировки. Рассмотрим более надежные способы реализации данной задачи.

Способ 1: Использование независимого регистра сведений

Вместо того чтобы хранить ДатаДоставки как реквизит самого документа «Заказ покупателя», вынесите это значение в независимый Регистр сведений. Это позволит:

Способ 2: Оптимизация работы с блокировками

Если вам все же необходимо изменять сам документ, проанализируйте, действительно ли вам нужна ЗаблокироватьДанныеДляРедактирования(). Часто достаточно просто правильно построить транзакцию и использовать БлокировкаДанных (объект платформы для работы с блокировками на уровне СУБД).

Пример корректного использования блокировки для записи данных:


// Создаем объект блокировки
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("Документ.ЗаказПокупателя");
ЭлементБлокировки.Значение = СсылкаНаЗаказ;
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;

НачатьТранзакцию();
Попытка
    Блокировка.Заблокировать();
    ОбъектДокумента = СсылкаНаЗаказ.ПолучитьОбъект();
    ОбъектДокумента.ОжидаемаяДатаВручения = НоваяДата;
    ОбъектДокумента.Записать();
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ВызватьИсключение;
КонецПопытки;

Рекомендации по итогам анализа

Разберем основные правила, которые помогут вам избежать подобных проблем в будущем:

Надеемся, данный разбор помог вам разобраться в механизмах платформы 1С и выбрать оптимальный путь для реализации вашей задачи!

← На главную