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