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