При разработке интеграций, интеграционных сервисов или специальных механизмов учета часто возникает задача: сохранить уникальный идентификатор объекта (UUID / GUID) в отдельный текстовый реквизит справочника или документа. Начинающие разработчики часто сталкиваются с проблемой, когда написанный в обработчиках событий код не заполняет реквизит или вызывает ошибки при создании нового объекта.
В этой статье мы подробно разберем, почему возникает такая проблема, проанализируем ошибки работы с событиями записи и составим правильный, отказоустойчивый алгоритм для решения этой задачи.
Рассмотрим распространенную ошибку, с которой сталкиваются разработчики. Допустим, в модуле объекта записан следующий код:
Процедура ПриЗаписи(Отказ)
ЭтотОбъект.УникальныйИдентификаторСтрока = Строка(Ссылка.УникальныйИдентификатор());
КонецПроцедуры
При выполнении этого кода реквизит УникальныйИдентификаторСтрока останется пустым в базе данных. Проанализируем, почему так происходит:
ПриЗаписи срабатывает в тот момент, когда объект уже записан в базу данных в рамках транзакции. Все изменения свойств объекта ЭтотОбъект, внесенные в процедуре ПриЗаписи, изменяют лишь данные в оперативной памяти текущего экземпляра, но в базу данных уже не попадают. Повторный вызов метода Записать() внутри ПриЗаписи приведет к зацикливанию системы.ПередЗаписью или ПриЗаписи) должны располагаться исключительно в модуле объекта, а не в модуле менеджера.Ссылка.УникальныйИдентификатор() не вернет сформированный идентификатор без предварительной установки ссылки нового.Разберем логику работы платформы 1С:Предприятие при создании нового объекта. По умолчанию ссылка для нового элемента генерируется платформой непосредственно в момент физической записи в базу данных. Однако разработчик имеет возможность сформировать ссылку заранее в оперативной памяти с помощью метода УстановитьСсылкуНового().
Рассмотрим, как правильно сгенерировать УникальныйИдентификатор и назначить его новому элементу в событии ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтоНовый() Тогда
// 1. Создаем новый УникальныйИдентификатор
НовыйУИД = Новый УникальныйИдентификатор;
// 2. Формируем ссылку на основе созданного УИД
БудущаяСсылка = Справочники.ХарактеристикиНоменклатуры.ПолучитьСсылку(НовыйУИД);
// 3. Назначаем эту ссылку текущему объекту
ЭтотОбъект.УстановитьСсылкуНового(БудущаяСсылка);
// 4. Записываем текстовое представление УИД в строковый реквизит
ЭтотОбъект.УникальныйИдентификаторСтрока = Строка(НовыйУИД);
КонецЕсли;
КонецПроцедуры
В этом коде процедура ПередЗаписью срабатывает до того, как данные отправятся в базу данных. Все изменения, внесенные в реквизиты объекта ЭтотОбъект на данном этапе, будут успешно сохранены в БД.
На практике приведенный выше простой пример требует двух важных дополнений:
ПередЗаписью также будет вызываться. Если не проверить свойство ОбменДанными.Загрузка, платформа заново перегенерирует GUID объекта, что приведет к рассинхронизации данных между базами.Рассмотрим итоговый универсальный алгоритм для модуля объекта:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Если происходит загрузка данных из внешних систем, отключаем логику переопределения
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Обрабатываем только новые объекты
Если ЭтоНовый() Тогда
// Проверяем, не была ли ссылка создана и установлена ранее
БудущаяСсылка = ПолучитьСсылкуНового();
Если НЕ ЗначениеЗаполнено(БудущаяСсылка) Тогда
// Если ссылка пустая, генерируем новый GUID и устанавливаем ссылку новому объекту
НовыйУИД = Новый УникальныйИдентификатор;
БудущаяСсылка = Справочники.ХарактеристикиНоменклатуры.ПолучитьСсылку(НовыйУИД);
УстановитьСсылкуНового(БудущаяСсылка);
Иначе
// Если ссылка уже была установлена ранее, извлекаем ее GUID
НовыйУИД = БудущаяСсылка.УникальныйИдентификатор();
КонецЕсли;
// Сохраняем строковое представление GUID в реквизит
УникальныйИдентификаторСтрока = Строка(НовыйУИД);
КонецЕсли;
КонецПроцедуры
Проанализируем ключевые особенности, которые необходимо учитывать при работе с ссылками и GUID в 1С:
УстановитьСсылкуНового() не создает физическую запись в таблицах базы данных до момента успешного завершения процедуры записи. Попытка выполнить запрос к таблице БД по созданной ссылке внутри процедуры ПередЗаписью не вернет данных.Строка(НовыйУИД) возвращает идентификатор в стандартном нижнем регистре с дефисами (например, e1a2b3c4-0000-0000-0000-000000000000). Если требуется формат для XML-обменов, можно использовать метод XMLСтрока(БудущаяСсылка).УникальныйИдентификатор(Ссылка), которая позволяет получать строковый GUID напрямую из ссылки в запросе.