В процессе разработки на платформе 1С:Предприятие часто возникают ситуации, когда после программного изменения данных через метод Объект.Записать(), последующее чтение этих же данных через ссылку выдает «устаревшие» значения. Давайте разберем, почему это происходит и как правильно организовать получение данных в таких случаях.
Когда мы обращаемся к реквизиту объекта через ссылку (например, Номенклатура.ВидНоменклатуры), платформа 1С пытается максимально оптимизировать процесс получения данных. В некоторых случаях, особенно при работе в рамках серверных вызовов или транзакций, платформа может использовать закэшированные значения, которые были считаны ранее. В итоге, несмотря на то что в базе данных запись уже успешно обновилась, при попытке прочитать обновленный реквизит через точку, мы получаем результат из кэша — старые данные.
Важно понимать: если вы откроете форму элемента вручную или выполните запись интерактивно, состояние кэша может обновиться, и вы увидите актуальную информацию. Однако в автоматизированных обработках надеяться на это нельзя.
Наиболее надежный и профессиональный способ получения данных в 1С — это использование механизма Запрос. Запрос всегда обращается к актуальному состоянию таблиц базы данных, минуя механизмы кэширования, которые могут затрагивать объектную модель. Давайте рассмотрим, как перестроить работу с таблицей значений, чтобы всегда получать свежую информацию.
Предположим, у нас есть задача заполнить таблицу товаров актуальными данными о виде номенклатуры. Вместо того чтобы «дотягиваться» до реквизита через ссылку, мы включим нужное поле непосредственно в выборку запроса.
Субконто1.ВидНоменклатуры), мы описываем это поле как полноценную колонку запроса. Это гарантирует, что движок запросов 1С выберет данные прямо из таблицы данных.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Номенклатура,
| ХозрасчетныйОстаткиИОбороты.Субконто1.ВидНоменклатуры КАК ВидНоменклатуры,
| СУММА(ХозрасчетныйОстаткиИОбороты.КоличествоКонечныйОстаток) КАК Количество
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&Период, , , , , , ) КАК ХозрасчетныйОстаткиИОбороты
|СГРУППИРОВАТЬ ПО
| ХозрасчетныйОстаткиИОбороты.Субконто1";
Как вы видите в примере, мы выводим ВидНоменклатуры как отдельное поле запроса. Это превращает его в «служебное поле» для вашей таблицы значений, которое уже не зависит от того, что «думает» объектная модель 1С в текущем контексте.
Давайте проанализируем преимущества такого подхода:
ПолучитьОбъект() для каждой строки в цикле. Вам не нужно инициализировать объект со всей его логикой (события ПриЗаписи, подписки и т.д.), если вам нужно только прочитать значение.Если ваша задача — изменить сотни элементов, не забывайте, что метод Объект.Записать() является «тяжелым» процессом. Он вызывает проверку всех подписок на события и заполнение регистров. Если вам нужно просто технически обновить реквизит, и при этом не требуется никакой дополнительной бизнес-логики, всегда оценивайте целесообразность использования методов работы с наборами записей или даже прямых методов записи. Но если вы используете именно Объект.Записать(), обязательно переходите на чтение данных через запрос для любых последующих операций вывода в таблицы или формы.
Итак, подведем итог: если вы столкнулись с тем, что «видите старое значение», прекращайте обращаться к реквизитам «через точку» в объектах. Формируйте качественный Запрос, извлекайте данные в ТЗ из него — и проблема неактуальности исчезнет раз и навсегда.