При работе с "Конвертацией Данных 2" (КД 2) для переноса регистров сведений, мы часто сталкиваемся с задачей не просто перенести данные, но и правильно управлять существующими записями в базе-приемнике. Это особенно актуально, когда нам необходимо обновить записи регистра, удалить устаревшие или изменить значения ресурсов, сохраняя при этом уникальность по измерениям. Давайте вместе разберем, как эффективно решить эту проблему, используя в том числе и универсальные обработки для обмена данными XML (удобно через универсальный перенос данных между базами 1С), расширяющие стандартные возможности платформы.
Основная сложность при переносе регистров сведений заключается в том, что система 1С объединяет записи с одинаковым набором измерений. Если в базе-источнике есть несколько записей с идентичными измерениями, в базе-приемнике они будут объединены в одну, что может привести к "сжатию" данных. Кроме того, при изменении значений ресурсов (например, поля Пользователь) для уже существующих наборов измерений, нам необходимо обеспечить корректное обновление, а не создание дубликатов или сохранение устаревших данных.
Один из наиболее надежных и часто используемых подходов — это явная очистка существующих записей регистра сведений в базе-приемнике перед загрузкой новых данных или в процессе их обработки. Если вам требуется выполнить массовые операции, можно использовать универсальную обработку для удаления и замены записей регистра по фильтрам. Однако внутри правил конвертации мы будем использовать механизм наборов записей с отбором, чтобы точечно удалять или перезаписывать данные.
Мы рассмотрим подробнее применение обработчика "После загрузки" в ПКО, поскольку именно на этом этапе нам уже доступен объект, который мы пытаемся загрузить, и мы можем использовать его измерения для формирования отбора.
Объект.Организация и Объект.Роль). Это позволит нам идентифицировать записи, которые соответствуют текущему набору измерений.Записать() для пустого набора записей с установленным отбором приведет к удалению всех записей регистра, которые соответствуют этому отбору. Это гарантирует, что старые записи с теми же измерениями будут удалены перед тем, как система запишет новые.Давайте посмотрим на пример кода для обработчика "После загрузки" ПКО:
НЗ = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
НЗ.Отбор.Организация.Установить(Объект.Организация);
НЗ.Отбор.Роль.Установить(Объект.Роль);
НЗ.Записать();
В этом примере, если в регистре МойРегистр уже существовали записи с такой же Организация и Роль, они будут удалены. После этого система продолжит загрузку данных, и новые записи будут добавлены или обновлены.
Иногда может потребоваться использовать Записать(Истина), чтобы явно указать, что набор записей должен быть полностью перезаписан:
НЗ = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
НЗ.Отбор.Организация.Установить(Объект.Организация, Истина); // Истина - для использования в отборе
НЗ.Отбор.Роль.Установить(Объект.Роль, Истина); // Истина - для использования в отборе
НЗ.Записать(Истина); // Истина - для записи набора записей с замещением
Важный момент: Использование НЗ.Записать() без параметров или с параметром Ложь записывает только те записи, которые были добавлены или изменены в самом наборе. Если набор пуст, он удалит записи по отбору. Если же в набор были добавлены новые записи, и мы хотим, чтобы они заменили все существующие по отбору, тогда НЗ.Записать(Истина) будет более подходящим.
Мы также можем рассмотреть вариант очистки данных в обработчике "Перед загрузкой" ПКО. Однако, в этом обработчике сам объект, который мы переносим, еще может быть недоступен в полной мере. Тем не менее, если мы знаем значения измерений заранее (например, они переданы через параметры), мы можем использовать этот подход:
Наборчик = РегистрыСведений.Вася.СоздатьНабор записей();
Наборчик.Отбор.Организация.Установить(ПараметрыОбъекта["Организация"]);
Наборчик.Отбор.Роль.Установить(ПараметрыОбъекта["Роль"]);
Наборчик.Записать();
Здесь мы используем ПараметрыОбъекта для получения значений измерений, что позволяет нам очистить записи до того, как начнется процесс загрузки текущего объекта.
Для более тонкой настройки выгружаемых данных и формирования нужного состава измерений мы можем использовать произвольный запрос в Правиле Выгрузки Данных (ПВД). Этот подход позволяет нам предварительно обработать данные еще на стороне источника, сгруппировав их или отфильтровав по определенным условиям. В качестве практического примера реализации таких правил можно изучить правила обмена между Комплексной автоматизацией 2.5 и WMS 5, где активно применяются механизмы КД 2 — для этой задачи подойдёт расширение механизмов КД 2 для обменов.
Мы можем сформировать запрос, который будет возвращать только необходимые нам данные, уже сгруппированные по измерениям, которые мы хотим видеть в приемнике. Это может упростить логику на стороне загрузки, так как мы будем уверены в уникальности данных по измерениям уже на этапе выгрузки.
Иногда возникает ситуация, когда поиск и идентификация записей должны происходить по одним полям, а затем необходимо заполнить или обновить другое поле, которое является измерением. В этом случае мы можем разместить поле-измерения в параметр.
Это означает, что при определении правил конвертации мы можем использовать определенные поля для поиска существующей записи, а затем, уже внутри обработчиков, использовать значения из параметров для заполнения или обновления других измерений или ресурсов. Например, если у нас есть измерение, которое не участвует в поиске напрямую, но должно быть заполнено, мы можем передать его значение через параметры и использовать в обработчике "После загрузки".
Давайте проанализируем дополнительные важные аспекты, которые помогут нам при переносе регистров сведений:
Флажок "Не запоминать выгруженные объекты": Для не ссылочных объектов, таких как строки регистров сведений, всегда устанавливайте флажок "Не запоминать выгруженные объекты" в Правиле Конвертации Объектов (ПКО). Ссылаться на отдельные строки регистра невозможно, и запоминание выгруженных строк только замедлит процесс и займет лишнюю память.
Безопасность и шифрование: Если данные регистра содержат конфиденциальную информацию, стоит обратить внимание на универсальную выгрузку-загрузку с возможностью шифрования, которая поддерживает работу с регистрами для всех конфигураций.
Независимые и подчиненные регистратору регистры:
Обработчики событий "Перед загрузкой" и "После загрузки данных":
Процедура ВыгрузитьПоПравилу(): При переносе данных из табличной части документа в регистр сведений, мы можем использовать процедуру ВыгрузитьПоПравилу(). В этом случае в ПКО для регистра сведений Источник остается пустым, а в приемнике указывается регистр сведений. Затем создается запрос для выборки данных из табличной части, и в обработчике "Перед выгрузкой" ПВД этот запрос выполняется, а данные передаются через параметр ВходящиеДанные в виде таблицы значений.
Мы должны быть внимательны к следующим особенностям:
Поведение ВыгрузитьРегистр() с отказом: Обратите внимание на особенность работы процедуры ВыгрузитьРегистр(). Если в Правиле Конвертации Объектов (ПКО) срабатывает отказ от выгрузки (например, Отказ = Истина;), XML-узел для регистра сведений все равно создается, но с пустым отбором. При загрузке это может привести к тому, что все записи регистра будут отобраны (поскольку отбор пустой) и перезаписаны пустым набором данных. Это может привести к потере миллионов записей! Всегда тщательно проверяйте логику отбора и отказа при работе с этой процедурой.
Регистры сведений, подчиненные регистратору: Если регистратор меняет дату, то при переносе в другую базу записи регистра сведений могут приходить как новые, а старые записи с прежней датой "подвисать". Необходимо продумать логику обработки таких ситуаций, возможно, через удаление старых записей по регистратору и дате.
Для повышения производительности и удобства, особенно в распределенных системах, мы рекомендуем следующие подходы:
Использование шин данных: Если стандартных возможностей XML-обмена недостаточно, можно внедрить современные инструменты, такие как связка Универсального обмена XML и RabbitMQ, что обеспечит более комфортную работу в сложных проектах.
Пообъектная передача: В случаях, когда важна оперативность, эффективным решением будет передача объектов по одному через RabbitMQ и КД2, что позволяет избежать накопления огромных файлов обмена.
Избегайте общих обработчиков: Не рекомендуется использовать общие обработчики событий для всех объектов, так как это может помешать оптимизациям. Лучше создавать отдельные алгоритмы и вызывать их в обработчиках нужных объектов.
Запись наборами записей: Режим записи изменений в регистрах наборами записей, а не менеджерами записей, позволяет сократить количество обращений к информационной базе и значительно ускорить процесс.
Применяя эти подходы, мы сможем обеспечить надежный и корректный перенос регистров сведений, избегая проблем с дубликатами, устаревшими данными и потерей информации.