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