При настройке правил обмена в конфигурации «Конвертация данных 2.1» нередко возникает задача получить скалярное значение из ссылочного объекта. Классический пример — выгрузка коэффициента единицы измерения в числовой реквизит документа приемника, если в документе источника хранится только ссылка на справочник ЕдиницыИзмерения или КлассификаторЕдиницИзмерения.
Рассмотрим, почему попытка создать отдельное ПКО (Правило конвертации объекта) с типом источника «СправочникСсылка» и типом приемника «Число» приводит к скрытым ошибкам и как правильно реализовать кэширование данных без лишней нагрузки на СУБД.
Архитектура конфигурации «Конвертация данных 2.1» и обработки «Универсальный обмен данными XML» разрабатывалась для работы со ссылочными типами данных и объектами метаданных (справочники, документы, регистры, перечисления). ПКО ожидает на входе и выходе полноценные структуры с XML-узлами свойств и идентификаторов объектов.
Если мы попытаемся настроить ПКО, где приемником выступает тип Число, мы столкнемся со следующими проблемами:
Нпп). На стороне базы-приемника скалярный числовой реквизит не сможет прочитать такую структуру, и значение будет потеряно или вызовет ошибку загрузки.Значение не является значением объектного типа во время выполнения выгрузки или загрузки.Разберем наиболее эффективный подход, позволяющий полностью исключить запросы к СУБД в цикле (обращения через точку к реквизитам единицы измерения при обработке строк документов).
Суть метода заключается в том, чтобы один раз перед началом выгрузки прочитать все нужные данные в оперативную память и сохранить их в структуру Параметры.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЕдиницыИзмерения.Ссылка КАК Ссылка,
| ЕдиницыИзмерения.Коэффициент КАК Коэффициент
|ИЗ
| Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения";
Выборка = Запрос.Выполнить().Выбрать();
Кэш = Новый Соответствие;
Пока Выборка.Следующий() Цикл
Кэш.Вставить(Выборка.Ссылка, Выборка.Коэффициент);
КонецЦикла;
Параметры.Вставить("КэшКоэффициентов", Кэш);
ПолучитьКоэффициентЕдиницы:
// Входящий параметр алгоритма: ЕдиницаИзмерения
// Возвращаемое значение: Число
Если Не ЗначениеЗаполнено(ЕдиницаИзмерения) Тогда
Значение = 1;
Иначе
КоэффициентИзКэша = Параметры.КэшКоэффициентов[ЕдиницаИзмерения];
Если КоэффициентИзКэша = Неопределено Тогда
// На случай, если элемент был создан динамически во время обмена
КоэффициентИзКэша = ЕдиницаИзмерения.Коэффициент;
Параметры.КэшКоэффициентов.Вставить(ЕдиницаИзмерения, КоэффициентИзКэша);
КонецЕсли;
Значение = ?(КоэффициентИзКэша = 0, 1, КоэффициентИзКэша);
КонецЕсли;
Коэффициент табличной части документа) в обработчике «Перед выгрузкой» или «При выгрузке» вызываем созданный алгоритм:
ЕдиницаИзмерения = ОбъектКоллекции.ЕдиницаИзмерения;
Выполнить(Алгоритмы.ПолучитьКоэффициентЕдиницы);
Если коэффициент требуется сразу в табличной части выгружаемого документа, проанализируем вариант с получением всех строк с соединенными реквизитами за один запрос к конкретному документу.
ИсходящиеДанные:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЧ.Номенклатура КАК Номенклатура,
| ТЧ.Количество КАК Количество,
| ЕСТЬNULL(ТЧ.ЕдиницаИзмерения.Коэффициент, 1) КАК Коэффициент
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК ТЧ
|ГДЕ
| ТЧ.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Источник);
ИсходящиеДанные = Новый Структура("Товары", Запрос.Выполнить().Выгрузить());
Посмотрим на ситуацию, когда коэффициент должен быть получен из справочника информационной базы-приемника. В этом случае в файл обмена достаточно передать ссылку на единицу измерения или ее код/наименование.
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
Если ЗначениеЗаполнено(СтрокаТЧ.ЕдиницаИзмерения) Тогда
СтрокаТЧ.Коэффициент = СтрокаТЧ.ЕдиницаИзмерения.Коэффициент;
Иначе
СтрокаТЧ.Коэффициент = 1;
КонецЕсли;
КонецЦикла;
Такой подход гарантирует целостность данных в приемнике и исключает проблемы несовпадения числовых реквизитов при различиях в классификаторах двух баз.