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