При разработке правил обмена в 1С:Конверсия данных 2.0 (КД2) программисты часто сталкиваются с необходимостью реализовать сложную логику выборки данных. Стандартных фильтров в Правилах выгрузки данных (ПВД) бывает недостаточно, и тогда мы прибегаем к использованию Произвольного алгоритма. Однако здесь кроется важный нюанс: как именно передаются данные из ПВД в Правила конверсии объектов (ПКО)? Многие ожидают увидеть в ПКО полноценный объект базы данных, но получают лишь строку выборки запроса. Разберем эту ситуацию подробно, изучим механизмы работы КД2 и выясним, как правильно организовать выгрузку.
Рассмотрим стандартную ситуацию. В ПВД в событии Перед обработкой вы определяете переменную ВыборкаДанных, куда помещаете результат выполнения запроса. Согласно документации, если эта переменная определена, система должна автоматически обойти коллекцию и выгрузить объекты. Логично ожидать, что в ПКО в событии Перед выгрузкой переменная Источник будет содержать объект (например, СправочникОбъект или ДокументОбъект). Но на практике там оказывается ВыборкаИзРезультатаЗапроса или Структура.
Проанализируем причину. Механизм КД2 спроектирован максимально гибко. Когда вы передаете коллекцию в ВыборкаДанных, система просто запускает цикл по этой коллекции. В ПКО в качестве Источник передается текущий элемент этой коллекции. Если вы передали результат запроса — ПКО получает строку этого запроса. Система не делает автоматического преобразования ссылки или строки в объект базы данных, так как это могло бы катастрофически снизить производительность обмена.
Самый очевидный, но не самый эффективный способ — это получить объект из ссылки непосредственно в ПКО. Если ваша выборка содержит поле Ссылка, вы можете написать в событии ПКО Перед выгрузкой следующий код:
// В ПКО "Перед выгрузкой"
Если ТипЗнч(Источник) = Тип("ВыборкаИзРезультатаЗапроса") Тогда
Источник = Источник.Ссылка.ПолучитьОбъект();
КонецЕсли;
Однако, как справедливо отмечают эксперты, такой подход считается "тяжелым". Представьте, что вы выгружаете 10 000 элементов. Выполнение метода ПолучитьОбъект() для каждого из них создаст 10 000 дополнительных обращений к базе данных, что значительно замедлит процесс выгрузки.
Выясним, как сделать выгрузку быстрее. На самом деле, ПКО вовсе не обязательно требует именно Объект. Оно прекрасно умеет работать со строкой выборки или структурой. Главное — обеспечить соответствие имен колонок в вашем запросе именам реквизитов в ПКО.
Рассмотрим алгоритм действий:
Источник (который является строкой выборки) поле с нужным именем.ОбъектКоллекции.Проанализируем ситуацию с производительностью: в этом случае вы делаете один большой запрос в ПВД, и ПКО просто "подхватывает" готовые данные из памяти, не обращаясь к базе за каждым объектом.
Если логика выбора ПКО зависит от сложных условий, которые невозможно описать простым сопоставлением, или если нужно выгружать данные по разным правилам в зависимости от значений полей, рекомендуется отказаться от автоматического заполнения ВыборкаДанных и использовать ручной цикл в ПВД Перед обработкой.
Посмотрим на пример реализации такого подхода:
// В ПВД "Перед обработкой"
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка, ВидОперации ИЗ Документ.РеализацияТоваровУслуг";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Определяем имя ПКО динамически
ИмяНужногоПКО = "";
Если Выборка.ВидОперации = Перечисления.ВидыОперацийРеализации.Товары Тогда
ИмяНужногоПКО = "РеализацияТоваров";
Иначе
ИмяНужногоПКО = "РеализацияУслуг";
КонецЕсли;
// Выгружаем объект вручную
ВыгрузитьПоПравилу(Выборка.Ссылка, , , , ИмяНужногоПКО);
КонецЦикла;
// Обязательно устанавливаем Отказ, чтобы штатный механизм не начал выгрузку
Отказ = Истина;
В этом примере мы передаем в ВыгрузитьПоПравилу именно Выборка.Ссылка. В этом случае КД2 сама поймет, что нужно работать с объектом (если ПКО настроено на поиск по ссылке), и вызовет событие Перед выгрузкой уже с объектом или ссылкой в качестве источника.
Иногда возникают ситуации, когда ПВД уже запущено через ВыборкаДанных, и нам нужно сменить правило "на лету". Разберем, как это работает. В КД2 в событии ПКО Перед выгрузкой можно изменить переменную ИмяПКО.
Важный момент: Если вы меняете ИмяПКО внутри самого ПКО, убедитесь, что структура данных в Источник совместима с новым правилом. Рассмотрим пример кода в ПКО:
// Событие ПКО "Перед выгрузкой"
Если Источник.ТипОперации = "Экспорт" Тогда
ИмяПКО = "РеализацияНаЭкспорт";
КонецЕсли;
После установки нового значения в ИмяПКО, текущая выгрузка будет перенаправлена на указанное правило. Это позволяет создавать "правила-заглушки", которые распределяют объекты по разным ПКО в зависимости от данных.
Когда мы используем произвольный алгоритм, часто нужно передать в ПКО данные, которых нет в самом объекте (например, какие-то рассчитанные в ПВД суммы или служебные флаги). Для этого используем структуру ВходящиеДанные.
Разберем по шагам:
ДопПараметры = Новый Структура("ЭтоСпецВыгрузка", Истина);.ВыгрузитьПоПравилу(Источник, , ДопПараметры, , "ИмяПКО");.Значение = ВходящиеДанные.ЭтоСпецВыгрузка;.Это избавляет от необходимости повторных запросов внутри ПКО и делает ваш код чище и быстрее.
Мы выяснили, что работа с ВыборкаДанных требует понимания того, какой именно тип данных передается в ПКО. Главное правило: КД2 не материализует объекты из выборки запроса автоматически. Для оптимизации работы следует либо использовать поля выборки напрямую, либо применять ручной цикл с ВыгрузитьПоПравилу, где вы полностью контролируете передаваемый Источник и ИмяПКО.