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