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