При работе с инструментом «Конвертация данных 2.0» (КД 2.0) разработчики часто сталкиваются с ситуацией, когда данные в базу-приемник передаются не в виде готовых объектов, а через произвольный запрос. Это особенно актуально для регистров сведений, информация в которые поступает из различных источников. Одной из главных проблем в этом случае становится «замусоривание» регистра: при повторной загрузке данных старые записи остаются, а новые добавляются или дублируются.
В этой статье мы подробно разберем, как реализовать механизм очистки данных регистра сведений по конкретному документу (регистратору или аналитике) таким образом, чтобы очистка происходила только один раз перед началом загрузки данных по этому объекту, не замедляя процесс и не удаляя только что загруженные строки.
Проанализируем типичную ситуацию. Допустим, мы передаем данные в регистр сведений, где в качестве одного из измерений (или регистратора) указан документ. В источнике мы используем запрос, который возвращает плоскую таблицу: для одного документа может быть 10, 100 или 1000 строк данных. Если мы пропишем очистку в обработчике ПередЗагрузкой или ПриЗагрузке для каждой записи регистра, то получим следующую логику: система загружает первую строку — чистит регистр — записывает строку. Затем загружает вторую строку — снова чистит регистр (удаляя первую загруженную) — записывает вторую. В итоге в базе останется только последняя строка из всего набора.
Нам же необходимо, чтобы при появлении первого упоминания документа в файле загрузки данные в регистре по нему полностью удалились, а все последующие строки этого же документа просто дописывались в чистый регистр.
Рассмотрим наиболее эффективный способ решения этой задачи — использование глобальной структуры Параметры, которая доступна во всех обработчиках КД 2.0 на протяжении всего сеанса загрузки данных. Этот метод позволяет нам «запоминать», для каких документов мы уже произвели очистку в текущей сессии.
Разберем реализацию по шагам.
Для начала нам нужно подготовить хранилище, где мы будем держать ссылки на уже «очищенные» документы. Лучшим местом для этого является обработчик «Перед загрузкой данных» в настройках самой конвертации. Этот код выполняется один раз в самом начале процесса загрузки.
Инициализируем список значений в глобальной структуре параметров:
// В обработчике "Перед загрузкой данных"
Параметры.Вставить("СписокОчищенныхДокументов", Новый СписокЗначений);
Теперь у нас есть пустой список, к которому мы сможем обращаться из любого ПКО (Правила конвертации объектов).
Теперь перейдем к самому правилу конвертации, которое отвечает за загрузку записей в регистр сведений. Нам потребуется обработчик «Перед загрузкой». Здесь мы будем проверять, встречался ли нам этот документ ранее в текущем файле обмена.
Предположим, что ссылка на документ-основание передается в свойство Объект (или это регистратор). Алгоритм будет следующим:
Параметры.СписокОчищенныхДокументов.Рассмотрим пример кода для обработчика Перед загрузкой:
// Получаем ссылку на документ из свойств загружаемого объекта
// В КД 2.0 параметры объекта доступны через структуру "Объект" или "ПараметрыОбъекта"
ДокументСсылка = Объект.ДокументОснование;
Если ДокументСсылка <> Неопределено И Не ДокументСсылка.Пустая() Тогда
// Проверяем, чистили ли мы уже регистр по этому документу
Если Параметры.СписокОчищенныхДокументов.НайтиПоЗначению(ДокументСсылка) = Неопределено Тогда
// Документ встретился впервые, нужно очистить старые записи в регистре
НаборЗаписей = РегистрыСведений.ИмяВашегоРегистра.СоздатьНаборЗаписей();
// Устанавливаем отбор по нашему документу
// ВАЖНО: Укажите правильное имя измерения или "Регистратор"
НаборЗаписей.Отбор.ДокументОснование.Установить(ДокументСсылка);
// Записываем пустой набор (очищаем данные в базе)
НаборЗаписей.Записать(Истина);
// Добавляем документ в список, чтобы больше его не чистить в этой сессии
Параметры.СписокОчищенныхДокументов.Добавить(ДокументСсылка);
// Сообщим для отладки (опционально)
// Сообщить("Регистр очищен по документу: " + ДокументСсылка);
КонецЕсли;
КонецЕсли;
Выясним причину, по которой мы используем РегистрСведенийНаборЗаписей вместо простого удаления. При использовании НабораЗаписей с установленным отбором и методом Записать(Истина), 1С максимально быстро и эффективно очищает все записи, попадающие под фильтр. Это гораздо надежнее, чем пытаться перебирать записи в цикле.
Важный момент: если ваш регистр сведений является подчиненным регистратору, то очистка через НаборЗаписей по регистратору — это стандартная и безопасная процедура. Если же регистр независимый, убедитесь, что в отборе участвуют все необходимые измерения, чтобы не удалить лишние данные, не относящиеся к текущей загрузке.
Иногда возникают ситуации, когда использование глобальных списков затруднено (например, при очень больших объемах данных, когда список может занять много оперативной памяти). В таком случае можно рассмотреть метод «временного флага».
Разберем этот сценарий по шагам:
ИдентификаторОбмена (тип Число или Строка).ИдентификаторОбмена.ИдентификаторОбмена не равен текущему номеру сессии.Этот метод сложнее в реализации, так как требует изменения структуры метаданных, но он гарантирует стопроцентную чистоту данных даже при прерывании процесса загрузки.
Мы проанализировали ситуацию и выяснили, что наиболее гибким и «чистым» решением для Конвертации данных 2.0 является комбинация использования структуры Параметры и программного управления набором записей. Этот подход позволяет:
Помните, что при работе с СписокЗначений в памяти, если объем уникальных документов исчисляется сотнями тысяч, стоит следить за потреблением ресурсов сервера. Однако для большинства стандартных задач обмена между базами 1С этот метод является эталонным.