В разработке на платформе 1С:Предприятие 8.3 часто возникает ситуация, когда результат сложного и длительного расчета, оформленного в виде временных таблиц (ВТ), требуется использовать повторно в другом серверном вызове. Типичный пример — разузлование продукции или расчет сложных себестоимостей. Основная сложность заключается в том, что в управляемом приложении между вызовами сервера контекст выполнения (включая менеджер временных таблиц) не сохраняется. Рассмотрим подробно, почему это происходит и какими способами можно решить данную задачу.
Проанализируем техническое устройство платформы. Объект МенеджерВременныхТаблиц является несериализуемым. Это означает, что его нельзя передать с сервера на клиент и обратно, а также нельзя сохранить в реквизит формы. Даже если вы попытаетесь поместить его во ВременноеХранилище или в ПараметрыСеанса, платформа выдаст ошибку при попытке сериализации данных. Каждый раз, когда выполнение серверного кода завершается и управление возвращается на клиент, все временные объекты, созданные в памяти сервера (включая временные таблицы в tempdb SQL-сервера, связанные с этим менеджером), уничтожаются, если на них не осталось ссылок.
Выясним, какие эффективные стратегии обхода этого ограничения существуют в арсенале разработчика 1С.
Это самый надежный и универсальный метод. Разберем его по шагам:
ТаблицуЗначений.ВременноеХранилище, используя уникальный идентификатор формы, чтобы данные жили, пока открыта форма.МенеджерВременныхТаблиц.Рассмотрим пример кода для первой кнопки:
&НаСервере
Процедура ВыполнитьПервыйЭтапНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура,
| Количество
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
| Справочник.Номенклатура";
// Менеджер здесь создается неявно или явно
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Выполнить();
// Выгружаем данные ВТ в таблицу значений
ЗапросВторой = Новый Запрос("ВЫБРАТЬ * ИЗ ВТ_Данные");
ЗапросВторой.МенеджерВременныхТаблиц = МенеджерВТ;
ТаблицаДанных = ЗапросВторой.Выполнить().Выгрузить();
// Сохраняем адрес в реквизит формы (тип Строка)
АдресХранилища = ПоместитьВоВременноеХранилище(ТаблицаДанных, ЭтаФорма.УникальныйИдентификатор);
КонецПроцедуры
Теперь проанализируем, как использовать эти данные во втором вызове:
&НаСервере
Процедура ВыполнитьВторойЭтапНаСервере()
Если ЭтоАдресВременногоХранилища(АдресХранилища) Тогда
ТаблицаДанных = ПолучитьИзВременногоХранилища(АдресХранилища);
НовыйЗапрос = Новый Запрос;
НовыйМенеджерВТ = Новый МенеджерВременныхТаблиц;
НовыйЗапрос.МенеджерВременныхТаблиц = НовыйМенеджерВТ;
// Загружаем ТЗ обратно во временную таблицу
НовыйЗапрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ВнешняяТЗ КАК ВнешняяТЗ";
НовыйЗапрос.УстановитьПараметр("ВнешняяТЗ", ТаблицаДанных);
НовыйЗапрос.Выполнить();
// Теперь ВТ_Данные снова доступна для работы
// ... дальнейшая логика запроса ...
КонецЕсли;
КонецПроцедуры
Если алгоритм формирования таблиц стандартизирован, мы можем применить механизм повторного использования возвращаемых значений. Посмотрим, как это работает. Мы создаем общий модуль с установленным свойством «Повторное использование: на время сеанса».
Однако здесь есть критический нюанс: возвращать сам МенеджерВременныхТаблиц нельзя из-за той же проблемы сериализации и привязки к контексту соединения. Если рабочий процесс 1С переключит соединение, менеджер станет невалидным. Поэтому в кэшируемом модуле лучше возвращать структуру с данными или ТаблицуЗначений, которую затем легко превратить в ВТ.
Если процесс формирования временных таблиц занимает много времени (как в случае с разузлованием), блокировка интерфейса пользователя крайне нежелательна. Проанализируем современный подход с использованием ФоновыеЗадания:
ВременноеХранилище.Такой подход позволяет пользователю не ждать окончания формирования таблиц, а интерфейс формы остается отзывчивым.
При использовании временных таблиц важно помнить о нагрузке на сервер базы данных. Посмотрим на основные правила «гигиены» при работе с МенеджеромВременныхТаблиц:
1. Контроль tempdb: Каждая временная таблица занимает физическое место в базе данных tempdb на SQL-сервере. Если ваши таблицы содержат сотни тысяч строк, многократное нажатие кнопок без очистки старых данных может привести к переполнению дискового пространства сервера.
2. Явное уничтожение: Если временная таблица больше не нужна в рамках одного запроса или цепочки вызовов, используйте команду УНИЧТОЖИТЬ. Это освобождает ресурсы немедленно, не дожидаясь закрытия менеджера или завершения сеанса. Для автоматической расстановки таких инструкций в сложных запросах можно использовать обработку для оптимизации временных таблиц в пакетах.
УНИЧТОЖИТЬ ВТ_Данные
3. Использование индексов: При передаче больших объемов данных через ТаблицуЗначений и последующую загрузку обратно в ВТ, не забудьте проиндексировать поля во временной таблице после загрузки, если планируете соединять её с другими таблицами в последующих запросах. Это значительно ускорит работу второго этапа.
Подводя итог, можно сказать, что наиболее сбалансированным решением для управляемых форм является связка Таблица Значений + Временное Хранилище. Это обеспечивает стабильность работы, предсказуемое поведение системы и независимость от контекста конкретного серверного вызова.