Как обновить закэшированные данные и реквизиты через точку в таблице на форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие 8 часто возникает ситуация, когда данные в таблице на управляемой форме «замерзают». Представим типичный сценарий: у нас есть таблица значений, в которой одна из колонок содержит ссылку на объект (например, Номенклатура), а рядом или в этой же таблице выведено поле, путь к данным которого прописан через точку — Номенклатура.Описание. Мы меняем описание объекта в базе данных, но на форме продолжаем видеть старое значение, даже если вызываем стандартные методы обновления. Проанализируем, почему так происходит, и разберем по шагам, как заставить систему отобразить актуальную информацию.

Выясним причину: почему стандартное обновление не помогает?

Для начала нам необходимо понять внутреннюю механику платформы. В 1С реализован мощный механизм кэширования объектов на стороне клиента. Когда форма обращается к реквизиту через точку (например, для отображения описания или артикула номенклатуры), платформа считывает это значение с сервера один раз и сохраняет его в оперативной памяти клиентского сеанса. Это критически важно для производительности, так как минимизирует количество «походов» на сервер при каждой перерисовке интерфейса.

Однако у этой медали есть обратная сторона. Если данные объекта изменились в базе данных (например, другой пользователь или фоновое задание изменили описание), клиентское приложение об этом «не знает». Оно продолжает считать данные в своем кэше актуальными. Проанализируем стандартные попытки решения, которые обычно не дают результата:

Основное решение: использование метода ОповеститьОбИзменении()

Для того чтобы «пробить» клиентский кэш, нам нужно послать системе четкий сигнал о том, что данные по конкретной ссылке больше не актуальны. Рассмотрим основной инструмент программиста — метод ОповеститьОбИзменении(). Этот метод сообщает всем открытым формам и спискам, что объект в базе данных был изменен.

Как только платформа получает этот сигнал, она помечает закэшированные данные указанной ссылки как недействительные. При следующем обращении к Номенклатура.Описание система будет вынуждена обратиться к серверу (или базе данных), чтобы получить свежее значение.

Посмотрим на пример кода, который необходимо выполнить после того, как данные объекта были изменены (например, в обработчике закрытия вспомогательной формы или после программной записи объекта):


// СсылкаНаОбъект - это ссылка на Номенклатуру, данные которой изменились
ОповеститьОбИзменении(СсылкаНаОбъект);

// После оповещения желательно принудительно обновить отображение текущей формы
ЭтаФорма.ОбновитьОтображениеДанных();

Различие в поведении Таблицы Значений и Динамического Списка

Проанализируем нюансы работы разных типов источников данных. Поведение платформы может отличаться в зависимости от того, что именно вы используете на форме.

  1. Динамический список с основной таблицей: Это «самый умный» объект. В большинстве случаев после вызова ОповеститьОбИзменении() он автоматически подхватывает изменения и обновляет строки на экране без дополнительных манипуляций.
  2. Динамический список БЕЗ основной таблицы (произвольный запрос): Здесь автоматика срабатывает не всегда. После оповещения системы об изменении ссылки, нам часто требуется явно вызвать метод Элементы.ИмяСписка.Обновить().
  3. Таблица значений (ДанныеФормыКоллекция): Это самый «ленивый» объект в плане обновления ссылочных данных через точку. Если вы программно заполнили таблицу значений, и ссылки в ней не менялись, платформа будет упорно показывать данные из кэша.

Если вы работаете именно с таблицей значений, рекомендуем использовать связку методов:


// 1. Сообщаем системе о недействительности кэша ссылки
ОповеститьОбИзменении(ИзмененнаяНоменклатура);

// 2. Пнем таблицу, чтобы она перерисовала данные из обновленного кэша
Элементы.ТаблицаНоменклатуры.Обновить();

// 3. На всякий случай обновляем всю форму
ЭтаФорма.ОбновитьОтображениеДанных();

Проблема «мертвого» кэша при повторном заполнении таблицы

Иногда возникают ситуации, когда даже закрытие и открытие обработки не помогает (как описывал автор темы). Это происходит из-за того, что сеанс пользователя продолжает хранить закэшированные данные объекта в памяти. Если вы программно очищаете и заново заполняете таблицу значений теми же самыми ссылками, платформа «узнает» знакомые ссылки и подставляет для них старые описания из оперативной памяти.

Чтобы гарантированно очистить данные в такой ситуации, можно применить прием «перезаписи» данных в колонке. Рассмотрим ситуацию программного заполнения:


Для Каждого Строка Из МояТаблицаЗначений Цикл
    // Сначала очищаем значение, чтобы разорвать связь с кэшем в текущем контексте отображения
    ТекущаяСсылка = Строка.Номенклатура;
    Строка.Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
    
    // Затем записываем ссылку обратно
    Строка.Номенклатура = ТекущаяСсылка;
    
    // И обязательно оповещаем систему, если мы знаем, что данные могли измениться
    ОповеститьОбИзменении(ТекущаяСсылка);
КонецЦикла;

Дополнительные рекомендации

Если программные методы не помогают, стоит обратить внимание на следующие моменты:

Параметры запуска: В самых крайних случаях, если кэш ведет себя непредсказуемо (например, при разработке и частом изменении метаданных), можно использовать ключ запуска /ClearCache. Однако это средство для разработчика, а не решение для конечного пользователя.

Оптимизация кода: Помните, что ОповеститьОбИзменении() — это глобальный вызов. Не стоит вызывать его в цикле для тысяч позиций, так как это может привести к кратковременному «подтормаживанию» интерфейса, пока все открытые списки будут пересчитывать свои данные. Если нужно обновить много позиций сразу, лучше вызвать оповещение только для тех ссылок, которые действительно изменились, или перечитать всю таблицу целиком с сервера.

Подводя итог, можно сказать: ключом к решению проблемы «старых данных» в таблицах 1С является управление клиентским кэшем через метод ОповеститьОбИзменении(). Это единственный надежный способ заставить платформу перечитать реквизиты объектов, обращение к которым идет «через точку».

← На главную