Как в Конвертации данных 2.1 выгрузить справочник в число и настроить кэширование значений?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При настройке правил обмена в конфигурации «Конвертация данных 2.1» нередко возникает задача получить скалярное значение из ссылочного объекта. Классический пример — выгрузка коэффициента единицы измерения в числовой реквизит документа приемника, если в документе источника хранится только ссылка на справочник ЕдиницыИзмерения или КлассификаторЕдиницИзмерения.

Рассмотрим, почему попытка создать отдельное ПКО (Правило конвертации объекта) с типом источника «СправочникСсылка» и типом приемника «Число» приводит к скрытым ошибкам и как правильно реализовать кэширование данных без лишней нагрузки на СУБД.

Почему не стоит использовать ПКО для примитивных типов

Архитектура конфигурации «Конвертация данных 2.1» и обработки «Универсальный обмен данными XML» разрабатывалась для работы со ссылочными типами данных и объектами метаданных (справочники, документы, регистры, перечисления). ПКО ожидает на входе и выходе полноценные структуры с XML-узлами свойств и идентификаторов объектов.

Если мы попытаемся настроить ПКО, где приемником выступает тип Число, мы столкнемся со следующими проблемами:

  1. Проблема повторного кэширования узлов (выгрузка «Нпп»): Встроенный механизм обмена оптимизирует повторную выгрузку ссылочных объектов. Если объект уже выгружался ранее по этому правилу, парсер вместо повторного значения записывает служебный узел номера по порядку (Нпп). На стороне базы-приемника скалярный числовой реквизит не сможет прочитать такую структуру, и значение будет потеряно или вызовет ошибку загрузки.
  2. Ошибки парсера метаданных: Попытка обращения к метаданным примитивного типа в контексте объекта метаданных может приводить к исключениям вида Значение не является значением объектного типа во время выполнения выгрузки или загрузки.

Решение 1. Предварительное пакетное кэширование в глобальных параметрах (рекомендуемый способ)

Разберем наиболее эффективный подход, позволяющий полностью исключить запросы к СУБД в цикле (обращения через точку к реквизитам единицы измерения при обработке строк документов).

Суть метода заключается в том, чтобы один раз перед началом выгрузки прочитать все нужные данные в оперативную память и сохранить их в структуру Параметры.

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

Решение 2. Выборка через «ИсходящиеДанные» в ПКО документа

Если коэффициент требуется сразу в табличной части выгружаемого документа, проанализируем вариант с получением всех строк с соединенными реквизитами за один запрос к конкретному документу.

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

Решение 3. Заполнение коэффициента на стороне приемника

Посмотрим на ситуацию, когда коэффициент должен быть получен из справочника информационной базы-приемника. В этом случае в файл обмена достаточно передать ссылку на единицу измерения или ее код/наименование.

  1. В ПКО документа на стороне приемника в обработчике «После загрузки» выполняем дозаполнение реквизитов:
    
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    	Если ЗначениеЗаполнено(СтрокаТЧ.ЕдиницаИзмерения) Тогда
    		СтрокаТЧ.Коэффициент = СтрокаТЧ.ЕдиницаИзмерения.Коэффициент;
    	Иначе
    		СтрокаТЧ.Коэффициент = 1;
    	КонецЕсли;
    КонецЦикла;
    

Такой подход гарантирует целостность данных в приемнике и исключает проблемы несовпадения числовых реквизитов при различиях в классификаторах двух баз.

← На главную