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

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

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

Почему нельзя просто сохранить Менеджер временных таблиц?

Проанализируем техническое устройство платформы. Объект МенеджерВременныхТаблиц является несериализуемым. Это означает, что его нельзя передать с сервера на клиент и обратно, а также нельзя сохранить в реквизит формы. Даже если вы попытаетесь поместить его во ВременноеХранилище или в ПараметрыСеанса, платформа выдаст ошибку при попытке сериализации данных. Каждый раз, когда выполнение серверного кода завершается и управление возвращается на клиент, все временные объекты, созданные в памяти сервера (включая временные таблицы в tempdb SQL-сервера, связанные с этим менеджером), уничтожаются, если на них не осталось ссылок.

Выясним, какие эффективные стратегии обхода этого ограничения существуют в арсенале разработчика 1С.

Способ 1. Передача через Таблицу Значений и Временное хранилище

Это самый надежный и универсальный метод. Разберем его по шагам:

  1. Выгрузка данных: При нажатии первой кнопки мы выполняем запрос и выгружаем результат временной таблицы в обычную ТаблицуЗначений.
  2. Помещение в хранилище: Помещаем полученную таблицу во ВременноеХранилище, используя уникальный идентификатор формы, чтобы данные жили, пока открыта форма.
  3. Восстановление данных: При нажатии второй кнопки извлекаем таблицу из хранилища и загружаем ее обратно в новый МенеджерВременныхТаблиц.

Рассмотрим пример кода для первой кнопки:


&НаСервере
Процедура ВыполнитьПервыйЭтапНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Номенклатура,
        |   Количество
        |ПОМЕСТИТЬ ВТ_Данные
        |ИЗ
        |   Справочник.Номенклатура";
    
    // Менеджер здесь создается неявно или явно
    МенеджерВТ = Новый МенеджерВременныхТаблиц;
    Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
    Запрос.Выполнить();
    
    // Выгружаем данные ВТ в таблицу значений
    ЗапросВторой = Новый Запрос("ВЫБРАТЬ * ИЗ ВТ_Данные");
    ЗапросВторой.МенеджерВременныхТаблиц = МенеджерВТ;
    ТаблицаДанных = ЗапросВторой.Выполнить().Выгрузить();
    
    // Сохраняем адрес в реквизит формы (тип Строка)
    АдресХранилища = ПоместитьВоВременноеХранилище(ТаблицаДанных, ЭтаФорма.УникальныйИдентификатор);
КонецПроцедуры

Теперь проанализируем, как использовать эти данные во втором вызове:


&НаСервере
Процедура ВыполнитьВторойЭтапНаСервере()
    Если ЭтоАдресВременногоХранилища(АдресХранилища) Тогда
        ТаблицаДанных = ПолучитьИзВременногоХранилища(АдресХранилища);
        
        НовыйЗапрос = Новый Запрос;
        НовыйМенеджерВТ = Новый МенеджерВременныхТаблиц;
        НовыйЗапрос.МенеджерВременныхТаблиц = НовыйМенеджерВТ;
        
        // Загружаем ТЗ обратно во временную таблицу
        НовыйЗапрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ВнешняяТЗ КАК ВнешняяТЗ";
        НовыйЗапрос.УстановитьПараметр("ВнешняяТЗ", ТаблицаДанных);
        НовыйЗапрос.Выполнить();
        
        // Теперь ВТ_Данные снова доступна для работы
        // ... дальнейшая логика запроса ...
    КонецЕсли;
КонецПроцедуры

Способ 2. Использование общих модулей с кэшированием

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

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

Способ 3. Оптимизация через Фоновые задания

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

  1. Первая кнопка запускает фоновое задание на сервере.
  2. Фоновое задание выполняет расчет и сохраняет результат в постоянную таблицу базы данных (например, в специально созданный регистр сведений или справочник-хранилище) либо помещает результат во ВременноеХранилище.
  3. Вторая кнопка просто считывает готовый результат, когда задание завершено.

Такой подход позволяет пользователю не ждать окончания формирования таблиц, а интерфейс формы остается отзывчивым.

Важные рекомендации по работе с ресурсами

При использовании временных таблиц важно помнить о нагрузке на сервер базы данных. Посмотрим на основные правила «гигиены» при работе с МенеджеромВременныхТаблиц:

1. Контроль tempdb: Каждая временная таблица занимает физическое место в базе данных tempdb на SQL-сервере. Если ваши таблицы содержат сотни тысяч строк, многократное нажатие кнопок без очистки старых данных может привести к переполнению дискового пространства сервера.

2. Явное уничтожение: Если временная таблица больше не нужна в рамках одного запроса или цепочки вызовов, используйте команду УНИЧТОЖИТЬ. Это освобождает ресурсы немедленно, не дожидаясь закрытия менеджера или завершения сеанса. Для автоматической расстановки таких инструкций в сложных запросах можно использовать обработку для оптимизации временных таблиц в пакетах.

УНИЧТОЖИТЬ ВТ_Данные

3. Использование индексов: При передаче больших объемов данных через ТаблицуЗначений и последующую загрузку обратно в ВТ, не забудьте проиндексировать поля во временной таблице после загрузки, если планируете соединять её с другими таблицами в последующих запросах. Это значительно ускорит работу второго этапа.

Подводя итог, можно сказать, что наиболее сбалансированным решением для управляемых форм является связка Таблица Значений + Временное Хранилище. Это обеспечивает стабильность работы, предсказуемое поведение системы и независимость от контекста конкретного серверного вызова.

← На главную