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