При организации обмена данными между информационными базами 1С через веб-сервисы частой задачей является передача справочников. На стороне источника данные формируются с помощью запроса и выгружаются в таблицу значений, после чего сериализуются в XML. На стороне приемника после выполнения десериализации с помощью объекта СериализаторXDTO мы получаем таблицу значений. Однако встает вопрос: каким образом правильным и безопасным путем записать полученные данные в иерархический справочник Номенклатура?
Рассмотрим по шагам алгоритм обработки полученной таблицы значений, разберем базовый пример кода записи элементов и групп, а также проанализируем важные технические нюансы, связанные с иерархией и производительностью.
Разберем классический подход к обходу таблицы значений и программному созданию или обновлению элементов справочника. Главная задача — правильно определить тип записи (группа или элемент), проверить существование ссылки в базе-приемнике и корректно перенести реквизиты.
Посмотрим на пример кода обработки десериализованной таблицы значений:
Для Каждого Стр Из ТЗ Цикл
Попытка
ЭтоГруппа = Ложь;
Если ТЗ.Колонки.Найти("ЭтоГруппа") <> Неопределено Тогда
ЭтоГруппа = Стр.ЭтоГруппа;
КонецЕсли;
// Проверяем существование объекта в базе по ссылке
Если Стр.Ссылка.ПолучитьОбъект() = Неопределено Тогда
Нов = ?(НЕ ЭтоГруппа, Справочники["Номенклатура"].СоздатьЭлемент(), Справочники["Номенклатура"].СоздатьГруппу());
Нов.УстановитьСсылкуНового(Стр.Ссылка);
Иначе
Нов = Стр.Ссылка.ПолучитьОбъект();
КонецЕсли;
// Заполняем реквизиты объекта
Если НЕ ЭтоГруппа Тогда
ЗаполнитьЗначенияСвойств(Нов, Стр, , "Ссылка");
Иначе
ЗаполнитьЗначенияСвойств(Нов, Стр, "Наименование, Код, Родитель");
КонецЕсли;
// Отключаем проверки платформы для режима загрузки
Нов.ОбменДанными.Загрузка = Истина;
Нов.Записать();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Проанализируем детально, как работают использованные в алгоритме механизмы платформы 1С:
ПолучитьОбъект() — вызванный у десериализованной ссылки Стр.Ссылка, возвращает Неопределено, если объект с таким уникальным идентификатором (GUID) еще не существует в информационной базе приемника. Это позволяет однозначно понять, требуется ли создавать новый элемент или нужно модифицировать существующий.УстановитьСсылкуНового() — метод, позволяющий сопоставить создаваемому объекту ровно тот GUID, который был у него в базе-источнике. Важно помнить, что этот метод можно вызывать только для новых, еще ни разу не записанных в информационную базу объектов до вызова метода Записать().ЗаполнитьЗначенияСвойств() — копирует значения одноименных колонок таблицы значений в реквизиты объекта. Для элемента исключается копирование поля Ссылка, а для группы заполняются только специфичные реквизиты иерархии.ОбменДанными.Загрузка = Истина — специальный флаг, который отключает выполнение подписок на события, проверки заполнения обязательных реквизитов и дополнительную бизнес-логику при записи. Это критически важно при интеграционных обменах для избежания конфликтов и циклических вызовов.При переносе иерархических справочников простым запросом через таблицу значений могут возникнуть подводные камни, которые необходимо учитывать:
Родитель, рекомендуется либо заранее сортировать таблицу значений по уровню иерархии (сначала группы верхних уровней, затем элементы), либо использовать двухпроходную запись (на первом проходе создаются все объекты с их GUID, на втором — заполняются реквизиты и связи).НачатьТранзакцию() и ЗафиксироватьТранзакцию() каждые 500–1000 элементов.Если справочники в базах полностью идентичны, более правильным архитектурным решением является сериализация не таблицы значений, а самого объекта СправочникОбъект через СериализаторXDTO. При таком подходе платформа автоматически сохраняет УИД, все реквизиты и табличные части объекта. На стороне приемника вызов СериализаторXDTO.ПрочитатьXML() сразу восстановит готовый объект справочника, у которого достаточно установить ОбменДанными.Загрузка = Истина и вызвать метод Записать().