При работе с технологией Конвертация данных 3.0 (КД3) и форматом Enterprise Data разработчики часто сталкиваются с тем, что архитектура обмена ориентирована в первую очередь на объекты ссылочного типа: справочники и документы. Регистры сведений, не имея ссылки, вызывают трудности при стандартной настройке правил. Разберем, почему возникает ошибка отсутствия поля Ссылка и как правильно организовать перенос записей регистров.
Стандартный механизм Библиотеки стандартных подсистем (БСП), который обслуживает КД3, при загрузке данных через ПКО (Правила конвертации объектов) ожидает, что результатом работы будет объект, обладающий свойством Ссылка. Это необходимо для регистрации объекта в массиве загруженных данных и последующей синхронизации по уникальному идентификатору.
Поскольку РегистрСведений — это не ссылочный тип данных, а набор записей, попытка системы выполнить код типа МассивЗагруженныхОбъектов.Добавить(ДанныеДляЗаписиВИБ.Ссылка) в общем модуле ОбменДаннымиXDTOСервер приводит к аварийному завершению загрузки. Рассмотрим, как обойти это ограничение, не внося изменений в типовые конфигурации.
Для загрузки регистров сведений наиболее эффективным методом является перенос логики записи из ПКО в ПОД (Правила обработки данных) в обработчик При обработке. Это позволяет полностью контролировать процесс записи набора записей и избежать обращения системы к несуществующим ссылкам.
Проанализируем алгоритм действий:
Рассмотрим пример кода, который можно разместить в обработчике При обработке для загрузки кадровых данных физических лиц:
// 1. Получаем правила конвертации для ссылочных полей (Организации, Физлица и т.д.)
ПравилоКонвертацииФизическиеЛица = ОбменДаннымиXDTOСервер.ПКОПоИмени(КомпонентыОбмена, "Справочник_ФизическиеЛица_Получение");
ПравилоКонвертацииДолжности = ОбменДаннымиXDTOСервер.ПКОПоИмени(КомпонентыОбмена, "Справочник_Должности_Получение");
ПравилоКонвертацииОрганизации = ОбменДаннымиXDTOСервер.ПКОПоИмени(КомпонентыОбмена, "Справочник_Организации_Получение");
// 2. Проверяем наличие записей в данных XDTO
Если ДанныеXDTO.Свойство("Записи") И ЗначениеЗаполнено(ДанныеXDTO.Записи) Тогда
Для Каждого СтрокаЗаписи Из ДанныеXDTO.Записи Цикл
// Создаем набор записей регистра
НаборЗаписей = РегистрыСведений.КадровыеДанныеФизлиц.СоздатьНаборЗаписей();
// Получаем ссылки из XDTO структур
СсылкаФизЛицо = ОбменДаннымиXDTOСервер.СтруктураОбъектаXDTOВДанныеИБ(КомпонентыОбмена, СтрокаЗаписи.ФизическоеЛицо, ПравилоКонвертацииФизическиеЛица, "ПолучитьСсылку").Ссылка;
СсылкаОрганизация = ОбменДаннымиXDTOСервер.СтруктураОбъектаXDTOВДанныеИБ(КомпонентыОбмена, СтрокаЗаписи.Организация, ПравилоКонвертацииОрганизации, "ПолучитьСсылку").Ссылка;
// Устанавливаем отборы для замещения конкретной записи
НаборЗаписей.Отбор.Период.Установить(СтрокаЗаписи.ДатаНачала);
НаборЗаписей.Отбор.Физлицо.Установить(СсылкаФизЛицо);
НаборЗаписей.Отбор.Организация.Установить(СсылкаОрганизация);
// Добавляем запись в набор
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = СтрокаЗаписи.ДатаНачала;
НоваяЗапись.Организация = СсылкаОрганизация;
НоваяЗапись.ФизЛицо = СсылкаФизЛицо;
НоваяЗапись.Должность = ОбменДаннымиXDTOСервер.СтруктураОбъектаXDTOВДанныеИБ(КомпонентыОбмена, СтрокаЗаписи.Должность, ПравилоКонвертацииДолжности, "ПолучитьСсылку").Ссылка;
НоваяЗапись.Активность = ИСТИНА;
// Записываем набор
НаборЗаписей.Записать();
КонецЦикла;
КонецЕсли;
Часто возникает ситуация, когда типовой объект формата Enterprise Data (например, Справочник.ОтветственныеЛица) не содержит всех необходимых полей для заполнения измерений вашего регистра. В этом случае мы используем свойство AdditionalInfo (Дополнительная информация).
Выясним, как передать сразу несколько параметров (например, период и идентификатор физлица), если AdditionalInfo кажется уже занятым. Вместо передачи одиночного значения мы можем упаковать данные в Структура. Система при выгрузке автоматически сериализует структуру в XML, а при загрузке позволит ее прочитать.
Пример выгрузки в ПКО_Отправка:
ДопДанные = Новый Структура;
ДопДанные.Вставить("ПериодЗаписи", ДанныеИБ.Отбор.ПериодЗаписи.Значение);
ДопДанные.Вставить("ФизЛицоУИД", Строка(ДанныеИБ.ФизЛицо.УникальныйИдентификатор()));
// Помещаем структуру в свойство AdditionalInfo XDTO-объекта
ДанныеXDTO.Вставить("AdditionalInfo", ДопДанные);
При получении данных в приемнике мы анализируем содержимое AdditionalInfo. Если там передана структура, извлекаем из нее значения для поиска ссылок или заполнения отборов регистра.
Проанализируем способ записи наборов. В примере выше метод НаборЗаписей.Записать() вызывается внутри цикла. Это допустимо для небольших объемов данных, однако при массовой загрузке (тысячи записей) это может существенно замедлить процесс обмена.
Рассмотрим оптимизированный подход:
Записать() один раз за итерацию по группе данных.ОбменДаннымиXDTOСервер.СсылкаОбъектаПоУИДОбъектаXDTO, если у вас есть только уникальный идентификатор объекта и вы уверены, что объект данного типа уже существует в базе-приемнике. Это работает быстрее, чем полноценный вызов СтруктураОбъектаXDTOВДанныеИБ через ПКО.Таким образом, синхронизация регистров сведений в КД3 требует ухода от стандартных автоматических механизмов загрузки в пользу ручного управления наборами записей через обработчики ПОД. Это дает гибкость в управлении отборами и позволяет корректно обрабатывать данные, не имеющие объектной ссылки.