Как обеспечить обновление данных в табличной части документа для других пользователей без перезапуска программы?

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

При работе с системой "1С:Предприятие" в клиент-серверном варианте, особенно при использовании тонкого клиента, мы часто сталкиваемся с проблемой несвоевременного отображения изменений данных, сделанных одним пользователем, у другого. Рассмотрим подробнее ситуацию, когда изменения в наименовании номенклатуры, внесенные из табличной части документа, не сразу видны другим пользователям, работающим с тем же документом.

Представим, что один из пользователей открыл документ, в котором есть табличная часть. Из этой табличной части он вызывает справочник номенклатуры и вносит изменения в наименование какого-либо элемента. Проблема заключается в том, что второй пользователь, который также работает с этим же документом, не видит внесенных изменений. Актуальные данные отображаются только после полного перезапуска программы. При этом важно отметить, что отчеты, использующие эту же номенклатуру, показывают актуальные данные сразу, без перезапуска программы. Даже повторный вход в документ не помогает обновить информацию в табличной части. Такая ситуация наблюдается для разных пользователей, включая администратора, при работе с базой данных на SQL-сервере через тонкий клиент.

Давайте выясним причину такого поведения и разберем способы решения данной проблемы.

Основные причины несвоевременного обновления данных и механизмы кэширования

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

  1. Кэширование в пределах формы: Система "1С" активно кэширует информацию, которую она получает для конкретной формы. Этот кэш обычно сбрасывается только при закрытии формы. То есть, если мы изменили данные, но форма осталась открытой, она может продолжать показывать старые данные из своего внутреннего кэша.
  2. Кэширование представлений ссылок: Одним из наиболее "ярких примеров" и частых источников проблем является кэширование представлений ссылок. Это означает, что если в табличной части документа отображается наименование номенклатуры (которое является представлением ссылки на элемент справочника "Номенклатура"), то это представление может быть закэшировано. Даже если сам объект "Номенклатура" был изменен в базе данных, его представление, уже загруженное в форму, не обновляется до тех пор, пока кэш представлений не будет очищен или обновлен. Именно поэтому отчеты, которые каждый раз формируют запрос к базе данных и не используют кэш представлений форм, сразу показывают актуальные данные.
  3. Локальный кэш тонкого клиента: Тонкий клиент также сохраняет на компьютере пользователя определенную информацию в виде локального кэша. Этот кэш используется для ускорения загрузки метаданных, форм, модулей и других ресурсов. Хотя он в меньшей степени влияет на актуальность оперативных данных по ссылкам, его наличие также способствует общему эффекту "несвежих" данных при определенных обстоятельствах.

Понимание этих механизмов кэширования позволяет нам перейти к рассмотрению эффективных способов решения проблемы.

Способы решения проблемы и обновления данных

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

1. Использование метода ОповеститьОбИзменении()

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

  1. Как это работает?

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

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

  2. Где вызывать?

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

    Пример кода:

    
    // Предположим, мы изменилиНаименованиеНоменклатуры
    // и записали ее.
            
    &НаКлиенте
    Процедура ПослеЗаписиИзмененийНоменклатуры()
        //...
        // Код изменения и записи номенклатуры
        // ...
        ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура"));
    КонецПроцедуры
    

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

2. Использование динамических списков

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

Если табличная часть документа использует динамический список для отображения связанных данных (например, список номенклатуры, выбранной в документе), то механизмы обновления динамического списка могут быть более эффективными для получения актуальной информации.

3. Обновление строк табличного поля

Если мы хотим обновить конкретную строку, группу строк или всю видимую область табличного поля, мы можем использовать метод ОбновитьСтроки() табличного поля. Этот метод имеет несколько вариантов использования:

  1. ТабличноеПоле.ОбновитьСтроки(); – Обновляет всю видимую область табличного поля, фактически перечитывая данные из источника для этих строк.
  2. ТабличноеПоле.ОбновитьСтроки(СтрокаТабличногоПоля); – Обновляет только указанную строку табличного поля.
  3. ТабличноеПоле.ОбновитьСтроки(МассивСтрокТабличногоПоля); – Обновляет группу строк, переданных в виде массива.

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

4. Очистка кэша вручную

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

  1. Запуск 1С с параметром /ClearCache: Мы можем запустить ярлык 1С с дополнительным параметром /ClearCache. Этот параметр очищает кэш клиент-серверных вызовов и заставляет систему перезагрузить метаданные и другие ресурсы.
  2. Удаление файлов кэша вручную: Файлы кэша тонкого клиента хранятся в директории AppData пользователя. Обычно это пути вида %LocalAppData%\1C\1CE\... и %AppData%\1C\1CE\.... Мы можем вручную удалить папки с хешами, но перед этим необходимо убедиться, что все сеансы 1С закрыты для данного пользователя.

5. Обходной путь (наблюдение из форума)

Как было замечено в обсуждении, иногда помогает следующий непрямой метод:

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

Дополнительные соображения

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

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

Таким образом, для решения описанной проблемы с несвоевременным обновлением данных в табличной части документа у другого пользователя, мы рекомендуем внедрить вызов метода ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура")); на клиенте сразу после того, как изменения в наименовании номенклатуры были записаны в базу данных. Это позволит своевременно обновить кэш представлений ссылок у других пользователей и обеспечит актуальность отображаемых данных.

← На главную