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