Как получить данные из временного хранилища, если известен только Уникальный Идентификатор (УИД)

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

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

Понятие адреса во временном хранилище и роль УИД

Для начала проанализируем, как работает метод ПоместитьВоВременноеХранилище(). Когда мы передаем в него данные, платформа возвращает уникальную строку — адрес. Если мы передаем вторым параметром УникальныйИдентификатор, мы фактически определяем "владельца" этих данных и время их жизни.

Рассмотрим стандартный пример, который вызывает вопросы:


УникальныйИдентификатор = Новый УникальныйИдентификатор("00000000-0000-0000-0000-123456781234");
Адрес = ПоместитьВоВременноеХранилище(МоиДанные, УникальныйИдентификатор);
// Далее по коду адрес теряется, остается только УИД

Важно понимать: функция ПолучитьИзВременногоХранилища() ожидает именно адрес (строку), а не сам объект типа УникальныйИдентификатор. Однако адрес во временном хранилище — это не случайный набор символов, а структурированный путь.

Решение 1: Реконструкция адреса из идентификатора

Малоизвестный, но крайне эффективный способ заключается в том, что адрес во временном хранилище имеет фиксированный префикс. Если вы жестко задали или сохранили УникальныйИдентификатор, вы можете восстановить адрес программно. Формат адреса следующий: e1cib/tempstorage/<UUID>.

Рассмотрим, как это реализовать на практике:


// Формируем адрес вручную на основании имеющегося УИД
МойУИД = Новый УникальныйИдентификатор("00000000-0000-0000-0000-123456781234");
СтрокаУИД = Формат(МойУИД, "ДФ=NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN");
СконструированныйАдрес = "e1cib/tempstorage/" + СтрокаУИД;

// Теперь мы можем получить данные
Попытка
    Данные = ПолучитьИзВременногоХранилища(СконструированныйАдрес);
Исключение
    // Обработка ситуации, если данные уже удалены или адрес неверен
КонецПопытки;

Внимание: Этот метод работает, но требует осторожности. Если вы используете произвольный УникальныйИдентификатор (не привязанный к форме), данные будут жить до конца сеанса пользователя. Это может привести к значительному потреблению оперативной памяти на сервере (rphost), если данных много и сеанс длится долго.

Решение 2: Использование Хранилища общих настроек

Если вам нужно передать адрес хранилища через цепочку процедур, где невозможно пробросить параметр, можно воспользоваться системным механизмом ХранилищеОбщихНастроек. Суть метода: помещаем данные во временное хранилище, а полученный адрес записываем в настройки под определенным ключом.

Разберем алгоритм действий:

  1. Помещаем объект во временное хранилище.
  2. Сохраняем адрес в ХранилищеОбщихНастроек с понятным ключом.
  3. В целевой процедуре читаем адрес из настроек и получаем объект.

Пример кода:


// На стороне отправителя
АдресХранилища = ПоместитьВоВременноеХранилище(ДеревоЗначений, Новый УникальныйИдентификатор);
ХранилищеОбщихНастроек.Сохранить("МойБуферДанных", "КлючДерева", АдресХранилища);

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

Этот способ надежен, так как настройки сохраняются в базе данных. Однако помните о необходимости очистки: после того как данные получены, желательно удалить запись из хранилища настроек, чтобы не засорять системные таблицы базы данных.

Решение 3: Использование методов БСП (Библиотеки стандартных подсистем)

Если ваша конфигурация построена на базе БСП, рекомендуется использовать готовые функции общего модуля ОбщегоНазначения. Это делает код более "чистым" и стандартизированным. Коллеги часто советуют использовать ЗаписатьДанныеВБезопасноеХранилище, но это не совсем верно для больших структур вроде деревьев значений, так как этот механизм предназначен для паролей и ключей с использованием шифрования.

Для нашей задачи лучше подходят обертки над хранилищем настроек:


// Сохранение данных (в качестве данных может выступать сам объект или адрес)
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить("ГруппаНастроек", "ИмяПараметра", Данные);

// Загрузка данных
Данные = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("ГруппаНастроек", "ИмяПараметра");

Преимущество функций БСП в том, что они корректно обрабатывают права доступа и могут сохранять данные как для конкретного пользователя, так и для всех пользователей сразу (если это необходимо для логики обмена).

Решение 4: Временные файлы как крайний случай

Проанализируем ситуацию, когда объем данных настолько велик, что помещение его в память сервера (временное хранилище) нежелательно. В этом случае можно использовать запись во временный файл. Чтобы разные сеансы не конфликтовали, имя файла можно генерировать на основе номера сеанса или уникального идентификатора.


// Запись в файл
ПутьКФайлу = КаталогВременныхФайлов() + "data_transfer_" + НомерСеанса() + ".dat";
Запись = Новый ЗаписьДанных(ПутьКФайлу);
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
Сериализатор.ЗаписатьXDTO(Запись, ДеревоЗначений);
Запись.Закрыть();

// Чтение в другой процедуре
Чтение = Новый ЧтениеДанных(ПутьКФайлу);
// ... логика восстановления объекта ...
Чтение.Закрыть();

Важный момент: Работа с файловой системой обычно медленнее, чем с оперативной памятью. Используйте этот метод только в исключительных случаях, когда работа с временным хранилищем вызывает переполнение памяти (Out of Memory).

Сравнительный анализ жизненного цикла данных

Выясним причину, по которой данные могут внезапно "исчезать" из временного хранилища. Это зависит от параметра УникальныйИдентификатор в функции помещения:

Рассмотрим подробнее риск "раздувания" памяти. Если вы используете жесткий УИД и помещаете туда данные в цикле или при частом нажатии кнопок пользователем, сервер 1С будет накапливать эти объекты до момента выхода пользователя из программы. Поэтому крайне важно вызывать УдалитьИзВременногоХранилища(Адрес) сразу после того, как данные стали не нужны.

Резюме и рекомендации

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

При выборе метода всегда учитывайте объем передаваемых данных и необходимость их очистки. Для небольших структур данных в пределах одного сеанса отлично подходят Параметры сеанса, которые доступны глобально и не требуют сложной манипуляции с адресами.

← На главную