В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда данные, помещенные во временное хранилище, ведут себя непредсказуемо. Одной из самых коварных проблем является "исчезновение" элементов массива: сам массив в хранилище остается, его длина совпадает с ожидаемой, но вместо объектов типа ДокументОбъект или СправочникОбъект внутри оказываются значения Неопределено. Разберем подробно, почему это происходит и как правильно спроектировать передачу данных между серверными вызовами.
Давайте проанализируем ситуацию. Тип данных ДокументОбъект является несериализуемым. Это означает, что он не может быть преобразован в последовательность байтов для передачи по сети или сохранения на диск. Он существует исключительно в оперативной памяти того рабочего процесса сервера (rphost), в котором был создан.
Рассмотрим, что происходит, когда мы выполняем следующий код:
// Ошибочный подход
&НаСервере
Функция ПолучитьАдресМассиваНовыхДокументовНаСервере()
МассивНовыхДокументов = Новый Массив;
НовыйДок = Документы.ЗаказПоставщику.СоздатьДокумент();
// ... заполнение реквизитов ...
МассивНовыхДокументов.Добавить(НовыйДок);
// Помещаем массив во временное хранилище
Адрес = ПоместитьВоВременноеХранилище(МассивНовыхДокументов, Новый УникальныйИдентификатор);
Возврат Адрес;
КонецФункции
Когда мы помещаем массив во временное хранилище, платформа 1С видит, что внутри массива находятся несериализуемые объекты. Вместо того чтобы честно сохранить состояние документа, она сохраняет лишь указатель на объект в памяти. Как только выполнение серверного вызова завершается, контекст может быть очищен, а объект удален сборщиком мусора.
Выясним причину, по которой код может работать "полгода без сбоев", а затем внезапно сломаться. В простейшем варианте (один сервер, один рабочий процесс rphost, мало пользователей) объект может задержаться в памяти. Но в полноценном кластере 1С ситуация иная:
rphost. В памяти этого процесса объекта не существует, и вы получаете Неопределено.Самый правильный и надежный способ — это передача данных в виде структур или таблиц значений. Эти типы данных являются сериализуемыми, они гарантированно сохраняются во временном хранилище и доступны любому рабочему процессу кластера.
Рассмотрим, как переписать заполнение документов через промежуточную структуру:
&НаСервере
Функция ПолучитьАдресМассиваСтруктурНаСервере()
МассивДанных = Новый Массив;
// Вместо объекта создаем структуру с реквизитами
ДанныеДокумента = Новый Структура;
ДанныеДокумента.Вставить("Дата", ТекущаяДата());
ДанныеДокумента.Вставить("Организация", Справочники.Организации.ПустаяСсылка());
// Для табличных частей используем массив структур или ТаблицуЗначений
ТЧ_Товары = Новый ТаблицаЗначений;
ТЧ_Товары.Колонки.Добавить("Номенклатура");
ТЧ_Товары.Колонки.Добавить("Количество");
// ... заполнение ТЧ ...
ДанныеДокумента.Вставить("Товары", ТЧ_Товары);
МассивДанных.Добавить(ДанныеДокумента);
Возврат ПоместитьВоВременноеХранилище(МассивДанных, Новый УникальныйИдентификатор);
КонецФункции
При таком подходе на стороне клиента вы получите адрес хранилища, из которого в любой момент сможете извлечь структуру и заполнить по ней ДанныеФормы или создать новый ДокументОбъект на сервере.
Если структура документа очень сложная и переписывать всё на Структуры трудозатратно, воспользуемся механизмом XDTO. Мы можем превратить объект в строку XML, которая прекрасно хранится и передается.
Разберем пример кода для сериализации:
// На сервере преобразуем объект в строку
СтрокаXML = СериализаторXDTO.ЗаписатьXML(ДокументОбъект);
МассивСтрок.Добавить(СтрокаXML);
Адрес = ПоместитьВоВременноеХранилище(МассивСтрок);
// Позже, когда нужно восстановить объект:
СтрокаИзХранилища = МассивИзХранилища[0];
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаИзХранилища);
ВосстановленныйОбъект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
Важный нюанс: СериализаторXDTO корректно работает только с теми данными, которые уже записаны в базу (имеют ссылку) или имеют четко определенную схему. Для новых, еще не записанных документов, этот метод может потребовать дополнительной настройки.
Проанализируем еще один момент из обсуждения: режим работы приложения. В Толстом клиенте (управляемое приложение) объекты могут существовать на стороне клиента. Если ваша задача — быстрое исправление "внутренней" обработки для администраторов, переключение в этот режим может временно помочь. Однако для типовых конфигураций (таких как УНФ, УТ 11, ERP) это является плохой практикой, так как современные конфигурации ориентированы на Тонкий и Веб-клиент.
Чтобы код работал стабильно независимо от фаз луны или настроек кластера серверов, придерживайтесь следующих правил:
ДокументОбъект, СправочникОбъект, Запрос, ЧтениеXML и подобные типы во временное хранилище для длительного хранения между серверными вызовами.КопироватьДанныеФормы(Откуда, Куда).ПоместитьВоВременноеХранилище без передачи второго параметра (УникальныйИдентификаторФормы) очищает данные при первом же следующем серверном вызове. Всегда привязывайте хранилище к идентификатору формы, если данные нужны для работы этой формы.Таким образом, "магия" исчезновения объектов — это лишь строгое соблюдение платформой правил работы с памятью и процессами. Переход на использование сериализуемых структур данных не только решит текущую проблему, но и сделает вашу систему готовой к масштабированию и работе в облачных сервисах.