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