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