При работе с системой "1С:Предприятие" в клиент-серверном варианте, особенно при использовании тонкого клиента, мы часто сталкиваемся с проблемой несвоевременного отображения изменений данных, сделанных одним пользователем, у другого. Рассмотрим подробнее ситуацию, когда изменения в наименовании номенклатуры, внесенные из табличной части документа, не сразу видны другим пользователям, работающим с тем же документом.
Представим, что один из пользователей открыл документ, в котором есть табличная часть. Из этой табличной части он вызывает справочник номенклатуры и вносит изменения в наименование какого-либо элемента. Проблема заключается в том, что второй пользователь, который также работает с этим же документом, не видит внесенных изменений. Актуальные данные отображаются только после полного перезапуска программы. При этом важно отметить, что отчеты, использующие эту же номенклатуру, показывают актуальные данные сразу, без перезапуска программы. Даже повторный вход в документ не помогает обновить информацию в табличной части. Такая ситуация наблюдается для разных пользователей, включая администратора, при работе с базой данных на SQL-сервере через тонкий клиент.
Давайте выясним причину такого поведения и разберем способы решения данной проблемы.
Основной причиной такого поведения является активное использование механизмов кэширования данных платформой "1С:Предприятие", особенно в последних версиях. Эти механизмы призваны ускорить работу системы и снизить нагрузку на сервер, но иногда приводят к отображению неактуальной информации.
Понимание этих механизмов кэширования позволяет нам перейти к рассмотрению эффективных способов решения проблемы.
Для того чтобы данные в табличной части документа обновлялись для всех пользователей своевременно, мы можем применить несколько подходов. Рассмотрим их подробнее.
ОповеститьОбИзменении()Наиболее эффективным и часто используемым способом является программное оповещение платформы об изменении объекта с помощью глобального метода ОповеститьОбИзменении(). Этот метод позволяет системе узнать, что данные по определенной ссылке были изменены, и принять меры для обновления кэша.
Когда мы вызываем ОповеститьОбИзменении(<Ссылка>), мы передаем в метод ссылку на объект (или ключ записи), об изменении которого хотим оповестить систему. Если передать Тип("СправочникСсылка.<ИмяСправочника>"), например, Тип("СправочникСсылка.Номенклатура"), это приводит к очистке кэша представлений всех ссылок, относящихся к данному типу справочника. После этого формы, которые ссылаются на измененный объект, могут обновить свои данные.
Этот метод уведомляет все динамические списки, что, в свою очередь, может привести к их обновлению, подтягивая актуальные данные из базы.
Вызывать метод ОповеститьОбИзменении() следует на клиенте после того, как изменения в справочнике (в нашем случае, в номенклатуре) были записаны в базу данных. Предположим, у нас есть процедура или функция, которая изменяет наименование номенклатуры и записывает ее. После выполнения этой операции нам необходимо добавить вызов оповещения.
Пример кода:
// Предположим, мы изменилиНаименованиеНоменклатуры
// и записали ее.
&НаКлиенте
Процедура ПослеЗаписиИзмененийНоменклатуры()
//...
// Код изменения и записи номенклатуры
// ...
ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура"));
КонецПроцедуры
Этот вызов сигнализирует платформе о том, что объект типа СправочникСсылка.Номенклатура был изменен. Если у другого пользователя в открытом документе есть табличное поле, где отображаются наименования номенклатуры, то после этого оповещения (иногда с небольшой задержкой, связанной с механизмом сообщений между клиентами) представление ссылок в его форме должно обновиться.
В управляемых формах, вместо того чтобы хранить все данные непосредственно в табличной части документа, мы можем использовать динамические списки. Динамический список сам по себе не хранит данные, а формирует их запросом при открытии формы. Он также может быть настроен на автоматическое обновление или обновляться по команде, подтягивая свежие данные из базы.
Если табличная часть документа использует динамический список для отображения связанных данных (например, список номенклатуры, выбранной в документе), то механизмы обновления динамического списка могут быть более эффективными для получения актуальной информации.
Если мы хотим обновить конкретную строку, группу строк или всю видимую область табличного поля, мы можем использовать метод ОбновитьСтроки() табличного поля. Этот метод имеет несколько вариантов использования:
ТабличноеПоле.ОбновитьСтроки(); – Обновляет всю видимую область табличного поля, фактически перечитывая данные из источника для этих строк.ТабличноеПоле.ОбновитьСтроки(СтрокаТабличногоПоля); – Обновляет только указанную строку табличного поля.ТабличноеПоле.ОбновитьСтроки(МассивСтрокТабличногоПоля); – Обновляет группу строк, переданных в виде массива.Этот подход может быть полезен, когда мы точно знаем, какая строка была изменена, и хотим обновить только ее, не затрагивая всю форму.
В некоторых случаях, если программные методы не дают желаемого результата или для целей отладки, мы можем прибегнуть к ручной очистке кэша тонкого клиента. Это не является решением для повседневной работы, но может помочь понять природу проблемы или решить ее в экстренных ситуациях:
/ClearCache: Мы можем запустить ярлык 1С с дополнительным параметром /ClearCache. Этот параметр очищает кэш клиент-серверных вызовов и заставляет систему перезагрузить метаданные и другие ресурсы.AppData пользователя. Обычно это пути вида %LocalAppData%\1C\1CE\... и %AppData%\1C\1CE\.... Мы можем вручную удалить папки с хешами, но перед этим необходимо убедиться, что все сеансы 1С закрыты для данного пользователя.Как было замечено в обсуждении, иногда помогает следующий непрямой метод:
Важно помнить, что проблема несвоевременного обновления данных в формах — это достаточно старая и известная особенность платформы "1С:Предприятие". При разработке мы должны учитывать, что внутренние оптимизирующие механизмы платформы не всегда детально понятны и контролируемы разработчиком конфигурации. Поэтому использование явных механизмов оповещения об изменениях, таких как ОповеститьОбИзменении(), является хорошей практикой.
Также стоит отметить, что при изменении данных табличной части через REST-интерфейс, например, обычно требуется перезаписывать табличную часть полностью, даже если изменяются только некоторые поля или строки, чтобы обеспечить консистентность данных.
Таким образом, для решения описанной проблемы с несвоевременным обновлением данных в табличной части документа у другого пользователя, мы рекомендуем внедрить вызов метода ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура")); на клиенте сразу после того, как изменения в наименовании номенклатуры были записаны в базу данных. Это позволит своевременно обновить кэш представлений ссылок у других пользователей и обеспечит актуальность отображаемых данных.