Как проверить изменение документа в 1С другим пользователем перед программной записью?

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

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

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

Оптимистическая блокировка и использование свойства ВерсияДанных

Самый правильный и платформенный путь — использование свойства ВерсияДанных. Это специальное строковое поле, которое платформа 1С генерирует автоматически и меняет при каждой успешной транзакции записи объекта в базу. В стандартных формах объектов эта проверка работает «под капотом», но в произвольных обработках механизм нужно реализовывать вручную.

Разберем по шагам, как правильно использовать этот механизм (оптимистическую блокировку):

  1. При чтении данных документа в обработку необходимо сохранить (закэшировать) текущее значение ВерсияДанных в отдельную переменную или реквизит формы обработки.
  2. Непосредственно перед вызовом метода записи или обработки данных, необходимо получить актуальную ссылку на документ из базы.
  3. Сравним актуальную версию с той, что мы сохранили при чтении. Если они отличаются, значит, документ был изменен кем-то другим, и необходимо выдать отказ.

Посмотрим на пример реализации логики перед записью:


АктуальныйОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если АктуальныйОбъект.ВерсияДанных <> СохраненнаяВерсияДанных Тогда
    Сообщить("Документ был изменен другим пользователем! Обновите данные.");
    Возврат;
КонецЕсли;

// Продолжаем логику записи, если версии совпадают
АктуальныйОбъект.Записать();

Альтернативный вариант: Хеширование данных

Еще один рабочий способ — сформировать хеш документа в момент чтения и сравнить его с хешем перед записью. Для этого используется платформенная функция ХешированиеДанных.

Алгоритм действий похож на работу с версией данных:

  1. При чтении получаем объект документа по ссылке и вычисляем его хеш.
  2. Сохраняем полученную хеш-сумму.
  3. Перед записью снова получаем объект, вычисляем хеш и сравниваем с сохраненным.

Этот метод работает надежно, но требует чуть больше вычислительных ресурсов на сериализацию и хеширование всего объекта по сравнению с простой проверкой встроенного свойства ВерсияДанных.

Пессимистическая блокировка: ЗаблокироватьДанныеДляРедактирования

Посмотрим на еще один подход, который предотвращает саму возможность изменения документа другим пользователем. Для этого используется метод ЗаблокироватьДанныеДляРедактирования().

Если ваша обработка вызовет этот метод в момент чтения документа, то объект будет заблокирован на уровне платформы. Это означает, что когда другой пользователь попытается открыть этот документ, система сразу уведомит его, что объект заблокирован.

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

Версионирование объектов и свойство Модифицированность

Часто начинающие разработчики пытаются использовать свойство ЭтаФорма.Модифицированность для проверок. Важно понимать: это свойство показывает лишь то, менял ли данные текущий пользователь в интерфейсе открытой формы. Оно не делает никаких запросов к СУБД и никак не поможет узнать, был ли объект изменен кем-то другим в параллельном сеансе.

Если в компании часто возникают коллизии и перезапись данных, настоятельно рекомендуем использовать типовой механизм «История изменений» (версионирование). При включенном версионировании каждое сохранение документа оставляет в базе его полный слепок. Если обработка случайно перезапишет ручные правки пользователя, вы всегда сможете открыть отчет по истории изменений, визуально сравнить версии и восстановить затертые данные в один клик.

← На главную