Как выгрузить иерархический справочник вместе со свойствами и родителями при использовании планов обмена в 1С

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

При организации интеграции между конфигурациями на платформе 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда одни и те же правила обмена данными (ПОД), созданные в конфигурации «Конвертация данных 2.1», ведут себя совершенно по-разному в зависимости от способа запуска. При выгрузке через встроенную обработку УниверсальныйОбменДаннымиXML справочник Номенклатура выгружается полностью: вместе с элементами переносится вся их иерархическая структура (родительские группы), а также связанные объекты (единицы измерения, номенклатурные группы, производители и другие ссылочные свойства). Однако при привязке этих же правил к узлу плана обмена в рамках регулярного online-обмена принимающая база получает лишь «пустые» ссылки — переносятся только уникальные идентификаторы (UID) и поля поиска родительских групп или свойств, в то время как сами эти объекты в базу-приемник не записываются. В этой статье мы подробно разберем, почему возникает такое поведение, проанализируем его причины и рассмотрим пять способов решения проблемы — от простых программных «костылей» до методологически верных архитектурных настроек.

Выясняем причину: почему оптимизация планов обмена «обрезает» связанные объекты

Для того чтобы понять природу этой проблемы, проанализируем внутренние механизмы работы платформы 1С и Библиотеки стандартных подсистем (БСП). Когда мы запускаем ручную выгрузку через обработку УниверсальныйОбменДаннымиXML, система по умолчанию обходит дерево ссылок выгружаемых объектов на всю доступную глубину. Если у элемента номенклатуры заполнено поле Родитель или указана ссылка на элемент справочника КлассификаторЕдиницИзмерения, обработка автоматически инициирует полную выгрузку этих связанных объектов, сериализуя их структуру в результирующий XML-файл.

В случае интеграции на основе планов обмена (особенно под управлением БСП) логика кардинально меняется. Здесь во главу угла ставится производительность и минимизация трафика. Система применяет жесткую оптимизацию: объекты, на которые есть ссылки в выгружаемом элементе, но которые сами не зарегистрированы на узле плана обмена, выгружаются исключительно в виде «узлов-ссылок» (передаются только GUID и ключевые поля поиска). Платформа исходит из предположения, что если объект (например, родительская группа или свойство) не был изменен в текущей сессии, то он уже существует в базе-приемнике, и передавать его повторно целиком нет никакой необходимости.

Это позволяет решить три важнейшие задачи:

  1. Предотвращение раздувания файлов обмена. Без этой оптимизации выгрузка одного элемента номенклатуры могла бы по цепочке повлечь за собой выгрузку половины информационной базы.
  2. Защита от бесконечной рекурсии (петли ссылок). Если объект «А» ссылается на «Б», а «Б» ссылается на «А», принудительный рекурсивный обход привел бы к переполнению стека и аварийному завершению процесса обмена.
  3. Ускорение синхронизации. Передача легких ссылочных узлов вместо полных XML-структур экономит ресурсы процессора и сетевой трафик.

Однако если в базе-приемнике этих связанных объектов еще нет (например, при первоначальном заполнении базы или если они были созданы только в источнике), мы получаем классическую проблему «битых ссылок» или неполных данных. Выясним, как мы можем управлять этим поведением.

Способ №1: Быстрое программное решение в ПКО (и его скрытые опасности)

Рассмотрим решение, которое часто находят разработчики на форумах (в частности, предложенное в сообщении №6 исходной темы). Оно заключается в принудительном отключении оптимизации планов обмена непосредственно в правилах конвертации объектов (ПКО).

Для этого в конфигурации «Конвертация данных 2.1» для ПКО нужного справочника (например, Номенклатура или ГруппыНоменклатуры) в обработчике события ПередВыгрузкой прописывается следующий код:


ВсеОбъектыВыгружены = Ложь;
ТолькоПолучитьУзелСсылки = Ложь;

Проанализируем работу этих переменных:

Важное предупреждение! Несмотря на то, что данный способ является самым простым в реализации и действительно решает локальную задачу «здесь и сейчас», применять его в реальных рабочих базах крайне не рекомендуется по следующим причинам:

  1. Высокий риск переполнения стека: Если в ваших справочниках возникнет циклическая ссылка, сервер 1С зависнет или упадет с критической ошибкой.
  2. Колоссальное снижение производительности: База данных начнет генерировать файлы обмена огромного размера. Процесс выгрузки, который раньше занимал секунды, может растянуться на часы.
  3. Затирание данных в приемнике: Любой импортированный объект будет полностью перезаписывать существующий объект в приемнике. Если в базе-приемнике велась независимая работа или были заполнены локальные реквизиты в этих справочниках, они будут безвозвратно стерты актуальными данными из источника при выгрузке любого ссылающегося на них элемента.

Способ №2: Использование стандартного режима БСП «Выгружать при необходимости»

Перейдем к более цивилизованным и безопасным методам. Если ваша конфигурация построена на базе БСП (Библиотека стандартных подсистем), лучшим решением будет использование встроенных режимов выгрузки объектов, определенных в составе плана обмена.

Разберем этот процесс по шагам:

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

Установка режима «Выгружать при необходимости» для вспомогательных справочников (классификаторы, группы, свойства) — это самый безопасный и методологически верный способ организации обмена без написания кода.

Способ №3: Использование флага в ПКО «Выгружать объект полностью, только при наличии на него ссылки»

Если интеграция настраивается непосредственно через правила конвертации в «Конвертации данных 2.1» и мы хотим зафиксировать это поведение на уровне самих правил, не полагаясь на настройки БСП в конфигураторе, мы можем использовать специальную настройку ПКО.

Рассмотрим, как это сделать:

  1. Откроем базу «Конвертация данных 2.1» и перейдем в список Правил Конвертации Объектов (ПКО).
  2. Найдем ПКО для нашего зависимого справочника (например, для справочника ЗначенияСвойствОбъектов или ГруппыНоменклатуры).
  3. Перейдем на вкладку «Общие настройки» (в некоторых версиях она называется «Настройки On-line обмена»).
  4. Установим флаг «Выгружать объект (полностью), только при наличии на него ссылки».

Эта настройка работает аналогично режиму БСП «Выгружать при необходимости». При выгрузке основного объекта (номенклатуры) обработчик обмена проанализирует правила для связанных объектов. Если у них взведен данный флаг, система выполнит их полную сериализацию, предотвращая появление пустых ссылок в базе-приемнике, но при этом сохранит защиту от бесконечной рекурсии и не будет выгружать эти справочники целиком без надобности.

Способ №4: Точечная выгрузка через ПКС с помощью переменной ВыгружатьОбъект

Иногда нам требуется гибкость: мы хотим, чтобы полностью выгружался не весь справочник со всеми связями, а только конкретные реквизиты конкретного объекта. Например, мы хотим, чтобы родительская группа выгружалась полностью, а вот справочник складов или контрагентов, указанных в свойствах, переносился только ссылкой.

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

Выполним следующие шаги:

  1. В «Конвертации данных 2.1» откроем ПКО справочника Номенклатура.
  2. Перейдем на вкладку «Правила конвертации свойств» и найдем ПКС для реквизита Родитель (или любого другого свойства, которое нужно выгрузить полностью).
  3. Откроем свойства этого ПКС и в обработчике события ПередВыгрузкой напишем простой код:

ВыгружатьОбъект = Истина;

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

Способ №5: Настройка Правил регистрации объектов (ПРО)

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

Для реализации этого подхода используются **Правила регистрации объектов (ПРО)**. Мы можем настроить их в «Конвертации данных 2.1» (раздел «Правила регистрации») или реализовать этот механизм в модуле плана обмена источника через подписки на события.

Рассмотрим пример реализации через подписку на событие ПередЗаписью или ПриЗаписи номенклатуры. Пропишем алгоритм, который при регистрации элемента номенклатуры автоматически находит всю цепочку его родителей и регистрирует их на узле плана обмена:


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

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

Сводное резюме: какой метод выбрать?

Для того чтобы облегчить выбор оптимального решения для вашего проекта, обобщим все рассмотренные методы в виде итоговых рекомендаций:

Мы надеемся, что этот подробный разбор механизмов сериализации и планов обмена поможет вам спроектировать надежную, быструю и отказоустойчивую систему интеграции ваших прикладных решений на платформе 1С:Предприятие.

← На главную