Часто при разработке собственных обработок в 1С возникает классическая проблема параллельной работы пользователей. Разберем типичную ситуацию: один пользователь открывает обработку, в которую считываются данные документа. Пока форма обработки открыта, он отвлекается на другие дела. В это время второй пользователь открывает этот же документ стандартным образом, вносит изменения и сохраняет его. Когда первый пользователь возвращается и нажимает кнопку записи в своей обработке, происходит перезапись документа устаревшими данными, и работа второго пользователя теряется.
Проанализируем, как можно предотвратить подобные коллизии и проверить, что документ был изменен в базе данных с момента его чтения. Рассмотрим несколько надежных способов решения этой задачи.
Самый правильный и платформенный путь — использование свойства ВерсияДанных. Это специальное строковое поле, которое платформа 1С генерирует автоматически и меняет при каждой успешной транзакции записи объекта в базу. В стандартных формах объектов эта проверка работает «под капотом», но в произвольных обработках механизм нужно реализовывать вручную.
Разберем по шагам, как правильно использовать этот механизм (оптимистическую блокировку):
ВерсияДанных в отдельную переменную или реквизит формы обработки.Посмотрим на пример реализации логики перед записью:
АктуальныйОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если АктуальныйОбъект.ВерсияДанных <> СохраненнаяВерсияДанных Тогда
Сообщить("Документ был изменен другим пользователем! Обновите данные.");
Возврат;
КонецЕсли;
// Продолжаем логику записи, если версии совпадают
АктуальныйОбъект.Записать();
Еще один рабочий способ — сформировать хеш документа в момент чтения и сравнить его с хешем перед записью. Для этого используется платформенная функция ХешированиеДанных.
Алгоритм действий похож на работу с версией данных:
Этот метод работает надежно, но требует чуть больше вычислительных ресурсов на сериализацию и хеширование всего объекта по сравнению с простой проверкой встроенного свойства ВерсияДанных.
Посмотрим на еще один подход, который предотвращает саму возможность изменения документа другим пользователем. Для этого используется метод ЗаблокироватьДанныеДляРедактирования().
Если ваша обработка вызовет этот метод в момент чтения документа, то объект будет заблокирован на уровне платформы. Это означает, что когда другой пользователь попытается открыть этот документ, система сразу уведомит его, что объект заблокирован.
Важный нюанс: У пессимистической блокировки есть существенный минус. Если первый пользователь оставит обработку открытой и уйдет на совещание или домой (не закрыв сеанс), документ «повиснет» в заблокированном состоянии. Никто другой не сможет внести в него изменения, пока сеанс первого пользователя не будет завершен принудительно администратором. Поэтому применять этот метод нужно крайне осторожно, только когда вы уверены в быстром завершении операции.
Часто начинающие разработчики пытаются использовать свойство ЭтаФорма.Модифицированность для проверок. Важно понимать: это свойство показывает лишь то, менял ли данные текущий пользователь в интерфейсе открытой формы. Оно не делает никаких запросов к СУБД и никак не поможет узнать, был ли объект изменен кем-то другим в параллельном сеансе.
Если в компании часто возникают коллизии и перезапись данных, настоятельно рекомендуем использовать типовой механизм «История изменений» (версионирование). При включенном версионировании каждое сохранение документа оставляет в базе его полный слепок. Если обработка случайно перезапишет ручные правки пользователя, вы всегда сможете открыть отчет по истории изменений, визуально сравнить версии и восстановить затертые данные в один клик.