Как правильно получить объекты при использовании произвольного алгоритма в КД 2.0

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

При разработке правил обмена в 1С:Конверсия данных 2.0 (КД2) программисты часто сталкиваются с необходимостью реализовать сложную логику выборки данных. Стандартных фильтров в Правилах выгрузки данных (ПВД) бывает недостаточно, и тогда мы прибегаем к использованию Произвольного алгоритма. Однако здесь кроется важный нюанс: как именно передаются данные из ПВД в Правила конверсии объектов (ПКО)? Многие ожидают увидеть в ПКО полноценный объект базы данных, но получают лишь строку выборки запроса. Разберем эту ситуацию подробно, изучим механизмы работы КД2 и выясним, как правильно организовать выгрузку.

Суть проблемы: почему в ПКО попадает не объект

Рассмотрим стандартную ситуацию. В ПВД в событии Перед обработкой вы определяете переменную ВыборкаДанных, куда помещаете результат выполнения запроса. Согласно документации, если эта переменная определена, система должна автоматически обойти коллекцию и выгрузить объекты. Логично ожидать, что в ПКО в событии Перед выгрузкой переменная Источник будет содержать объект (например, СправочникОбъект или ДокументОбъект). Но на практике там оказывается ВыборкаИзРезультатаЗапроса или Структура.

Проанализируем причину. Механизм КД2 спроектирован максимально гибко. Когда вы передаете коллекцию в ВыборкаДанных, система просто запускает цикл по этой коллекции. В ПКО в качестве Источник передается текущий элемент этой коллекции. Если вы передали результат запроса — ПКО получает строку этого запроса. Система не делает автоматического преобразования ссылки или строки в объект базы данных, так как это могло бы катастрофически снизить производительность обмена.

Решение 1: Получение объекта внутри ПКО

Самый очевидный, но не самый эффективный способ — это получить объект из ссылки непосредственно в ПКО. Если ваша выборка содержит поле Ссылка, вы можете написать в событии ПКО Перед выгрузкой следующий код:


// В ПКО "Перед выгрузкой"
Если ТипЗнч(Источник) = Тип("ВыборкаИзРезультатаЗапроса") Тогда
    Источник = Источник.Ссылка.ПолучитьОбъект();
КонецЕсли;

Однако, как справедливо отмечают эксперты, такой подход считается "тяжелым". Представьте, что вы выгружаете 10 000 элементов. Выполнение метода ПолучитьОбъект() для каждого из них создаст 10 000 дополнительных обращений к базе данных, что значительно замедлит процесс выгрузки.

Решение 2: Использование полей выборки (Оптимальный путь)

Выясним, как сделать выгрузку быстрее. На самом деле, ПКО вовсе не обязательно требует именно Объект. Оно прекрасно умеет работать со строкой выборки или структурой. Главное — обеспечить соответствие имен колонок в вашем запросе именам реквизитов в ПКО.

Рассмотрим алгоритм действий:

  1. В запросе ПВД выбираем все необходимые поля (включая поля через точку, если нужно).
  2. В ПКО для свойств (ПКС) оставляем стандартное получение данных. КД2 сама попробует найти в Источник (который является строкой выборки) поле с нужным именем.
  3. Если имена не совпадают, в ПКС можно явно прописать получение из ОбъектКоллекции.

Проанализируем ситуацию с производительностью: в этом случае вы делаете один большой запрос в ПВД, и ПКО просто "подхватывает" готовые данные из памяти, не обращаясь к базе за каждым объектом.

Решение 3: Ручной обход и ВыгрузитьПоПравилу

Если логика выбора ПКО зависит от сложных условий, которые невозможно описать простым сопоставлением, или если нужно выгружать данные по разным правилам в зависимости от значений полей, рекомендуется отказаться от автоматического заполнения ВыборкаДанных и использовать ручной цикл в ПВД Перед обработкой.

Посмотрим на пример реализации такого подхода:


// В ПВД "Перед обработкой"
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка, ВидОперации ИЗ Документ.РеализацияТоваровУслуг";
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    
    // Определяем имя ПКО динамически
    ИмяНужногоПКО = "";
    Если Выборка.ВидОперации = Перечисления.ВидыОперацийРеализации.Товары Тогда
        ИмяНужногоПКО = "РеализацияТоваров";
    Иначе
        ИмяНужногоПКО = "РеализацияУслуг";
    КонецЕсли;
    
    // Выгружаем объект вручную
    ВыгрузитьПоПравилу(Выборка.Ссылка, , , , ИмяНужногоПКО);
    
КонецЦикла;

// Обязательно устанавливаем Отказ, чтобы штатный механизм не начал выгрузку
Отказ = Истина;

В этом примере мы передаем в ВыгрузитьПоПравилу именно Выборка.Ссылка. В этом случае КД2 сама поймет, что нужно работать с объектом (если ПКО настроено на поиск по ссылке), и вызовет событие Перед выгрузкой уже с объектом или ссылкой в качестве источника.

Динамический выбор ПКО в событии "Перед выгрузкой"

Иногда возникают ситуации, когда ПВД уже запущено через ВыборкаДанных, и нам нужно сменить правило "на лету". Разберем, как это работает. В КД2 в событии ПКО Перед выгрузкой можно изменить переменную ИмяПКО.

Важный момент: Если вы меняете ИмяПКО внутри самого ПКО, убедитесь, что структура данных в Источник совместима с новым правилом. Рассмотрим пример кода в ПКО:


// Событие ПКО "Перед выгрузкой"
Если Источник.ТипОперации = "Экспорт" Тогда
    ИмяПКО = "РеализацияНаЭкспорт";
КонецЕсли;

После установки нового значения в ИмяПКО, текущая выгрузка будет перенаправлена на указанное правило. Это позволяет создавать "правила-заглушки", которые распределяют объекты по разным ПКО в зависимости от данных.

Использование ВходящихДанных для передачи контекста

Когда мы используем произвольный алгоритм, часто нужно передать в ПКО данные, которых нет в самом объекте (например, какие-то рассчитанные в ПВД суммы или служебные флаги). Для этого используем структуру ВходящиеДанные.

Разберем по шагам:

  1. В ПВД формируем структуру: ДопПараметры = Новый Структура("ЭтоСпецВыгрузка", Истина);.
  2. Передаем её в функцию: ВыгрузитьПоПравилу(Источник, , ДопПараметры, , "ИмяПКО");.
  3. В ПКО или ПКС обращаемся к этим данным: Значение = ВходящиеДанные.ЭтоСпецВыгрузка;.

Это избавляет от необходимости повторных запросов внутри ПКО и делает ваш код чище и быстрее.

Подведем итоги

Мы выяснили, что работа с ВыборкаДанных требует понимания того, какой именно тип данных передается в ПКО. Главное правило: КД2 не материализует объекты из выборки запроса автоматически. Для оптимизации работы следует либо использовать поля выборки напрямую, либо применять ручной цикл с ВыгрузитьПоПравилу, где вы полностью контролируете передаваемый Источник и ИмяПКО.

← На главную