Использование обработчика ОбработкаПолученияПредставления в модуле менеджера объекта — это мощный инструмент для кастомизации интерфейса. Однако, если внутри этого обработчика начать обращаться к реквизитам через точку (например, Данные.Ответственный.Наименование), система может столкнуться с серьезными проблемами производительности. Разберем подробно, почему это происходит и какими способами можно реализовать данную задачу правильно.
Рассмотрим ситуацию: у нас есть динамический список, в котором отображается 100 строк. Для каждой строки платформа вызывает обработчик получения представления. Если внутри кода происходит обращение к ссылочному реквизиту, платформа выполняет отдельный SQL-запрос к базе данных для получения этого значения. В итоге вместо одного запроса для получения списка мы получаем 1 + 100 запросов. Это значительно замедляет работу системы, особенно в «километровых» отчетах или при сортировке таблиц значений. Проанализируем основные методы решения этой проблемы.
Для того чтобы избежать лишних запросов, в платформе предусмотрен парный обработчик — ОбработкаПолученияПолейПредставления. Рассмотрим его работу по шагам. Этот метод позволяет «сказать» платформе, какие именно поля (включая поля через точку) ей нужно извлечь из базы данных одним общим запросом вместе с основной информацией об объекте.
В модуле менеджера объекта определим состав необходимых полей:
Процедура ОбработкаПолученияПолейПредставления(Поля, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Поля.Добавить("Номер");
Поля.Добавить("Дата");
Поля.Добавить("Ответственный.Наименование");
Поля.Добавить("КонтактноеЛицо.Наименование");
КонецПроцедуры
Теперь в основном обработчике данные этих полей уже будут доступны в структуре Данные, и повторного обращения к базе не произойдет:
Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ИмяОтветственного = "";
Если Данные.Свойство("Ответственный_Наименование") Тогда
ИмяОтветственного = Данные.Ответственный_Наименование;
КонецЕсли;
Представление = СтрШаблон("Документ №%1 от %2 (%3)", Данные.Номер, Формат(Данные.Дата, "ДЛФ=D"), ИмяОтветственного);
КонецПроцедуры
Важный нюанс: Обратите внимание, что при использовании полей через точку в структуре Данные они часто приходят с заменой точки на подчеркивание (например, Ответственный_Наименование). Это позволяет эффективно формировать строку представления без единого дополнительного запроса к СУБД.
Посмотрим на ситуацию под другим углом. Если алгоритм формирования представления очень сложный или данные меняются редко, наиболее производительным решением будет создание специального строкового реквизита (например, НаименованиеСлужебное). Разберем, как это реализовать:
ПредставлениеОбъекта с типом Строка.ПередЗаписью прописываем логику заполнения этого реквизита.ОбработкаПолученияПредставления просто возвращаем значение этого реквизита.Пример кода в модуле объекта:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Формируем строку заранее
ТекстОтветственного = ?(ЗначениеЗаполнено(Ответственный), Ответственный.Наименование, "Без ответственного");
ПредставлениеОбъекта = СтрШаблон("%1 от %2 [%3]", Номер, Формат(Дата, "ДЛФ=D"), ТекстОтветственного);
КонецПроцедуры
Этот метод считается «базой» во многих типовых конфигурациях (например, так работает справочник ФизическиеЛица). Это исключает любые расчеты «на лету» и позволяет выполнять мгновенный поиск по строке представления.
Выясним, как работает кэширование в контексте представлений. Платформа 1С автоматически кэширует представления объектов на время сеанса. Однако, если вам нужно программно оптимизировать получение данных внутри модуля менеджера, можно использовать функции с повторным использованием возвращаемых значений.
Рассмотрим пример создания оптимизированного метода в общем модуле:
// В общем модуле с установленным флагом "Повторное использование: На время сеанса"
Функция ПолучитьДанныеДляПредставления(Ссылка) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номер, Дата, Ответственный.Наименование КАК ФИО ИЗ Документ.Заявка ГДЕ Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
// ... выполнение запроса и возврат структуры
КонецФункции
Однако помните, что избыточное использование кэша на сервере может привести к повышенному потреблению оперативной памяти, поэтому кэшировать стоит только действительно «тяжелые» или часто запрашиваемые данные.
Проанализируем ситуацию, когда представление зависит от данных других объектов (например, изменилась фамилия ответственного лица). Если мы используем Решение 2 (хранение в реквизите), представление в нашем документе станет неактуальным. Для решения этой задачи можно применить следующие подходы:
ПриЗаписи для справочника Пользователи. При изменении фамилии подписка находит все связанные документы и обновляет в них поле ПредставлениеОбъекта.ОбработкаПолученияПолейПредставления (Решение 1) всегда гарантирует актуальность, так как данные читаются из базы в момент формирования списка.Подводя итог, можно сказать, что выбор метода зависит от конкретной задачи:
ОбработкаПолученияПолейПредставления. Это «золотая середина» между скоростью и актуальностью.НаименованиеСлужебное.Новый Запрос внутри ОбработкаПолученияПредставления без механизмов кэширования или предварительного отбора полей, так как это гарантированно приведет к деградации производительности всей системы.