К статье
Практический материал

Разработка и Конфигурация · 9 мин

1С: как проверить, записан объект или нет

Как в 1С проверить, что объект записан в базу: функция ЗначениеЗаполнено, ПустаяСсылка, НовыйОбъект, проверка ссылки и типичные ошибки при проверке записи.

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

Существует несколько принципиально разных ситуаций: объект создан, но ещё не записан; ссылка есть, но объекта в базе нет (битая ссылка); ссылка пустая вообще. Для каждой ситуации встроенный язык 1С предлагает свой инструмент, и смешивать их нельзя — проверка, подходящая для одного случая, в другом даст неверный результат.

Ниже разобраны основные способы проверки: через свойство ссылки, через запрос к базе, через попытку получения объекта и через служебные функции. Для каждого способа указаны условия применения и ограничения.

Чем отличается объект от ссылки и почему это важно

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

После записи объект получает уникальный идентификатор, и ссылка становится заполненной. Однако обратное неверно: заполненная ссылка не гарантирует, что объект существует. Запись могли удалить, а ссылка осталась в других документах или регистрах — это классическая «битая ссылка», выглядящая как строка «Объект не найден».

Проверка, записан ли новый объект: ПустаяСсылка и НовыйОбъект

Самый простой сценарий — вы создали объект программно и хотите понять, записан ли он. Для этого достаточно проверить его ссылку:

НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

Если НовыйДок.Ссылка.Пустая() Тогда

// Объект ещё не записан в базу

КонецЕсли;

НовыйДок.Записать();

Если Не НовыйДок.Ссылка.Пустая() Тогда

// Теперь объект записан

КонецЕсли;

Также полезен метод ЭтоНовый(), который возвращает Истина, пока объект ни разу не был записан. Разница тонкая: Ссылка.Пустая() проверяет состояние ссылки, а ЭтоНовый() — состояние самого объекта в памяти. На практике для только что созданного объекта они дают одинаковый результат, но после ПолучитьОбъект() у существующей записи ЭтоНовый() вернёт Ложь.

Проверка существования объекта по ссылке

Когда ссылка получена извне — из реквизита документа, из параметра процедуры, из файла обмена, — нужно убедиться, что объект по ней реально есть в базе. Самый надёжный способ — запрос:

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 ИСТИНА ИЗ Документ.РеализацияТоваровУслуг ГДЕ Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);

Если Запрос.Выполнить().Пустой() Тогда

// Объекта в базе нет — ссылка битая

КонецЕсли;

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

Обращение к реквизитам битой ссылки через точку (например, Ссылка.Номер) не вызывает исключения, но возвращает неопределённые или пустые значения, что маскирует проблему. Поэтому явная проверка существования предпочтительнее, чем анализ косвенных признаков.

Порядок проверки ссылки
  1. 1
    Убедитесь, что ссылка заполнена: НЕ Ссылка.Пустая()
  2. 2
    Проверьте существование объекта запросом или ОбщегоНазначения.СсылкаСуществует()
  3. 3
    Только после этого обращайтесь к реквизитам или вызывайте ПолучитьОбъект()
  4. 4
    При отсутствии объекта залогируйте ситуацию и пропустите обработку

Проверка через ПолучитьОбъект и обработка исключений

Альтернативный подход — попытаться получить объект и проверить результат. Метод ПолучитьОбъект() у несуществующей ссылки возвращает Неопределено, а не вызывает ошибку:

ОбъектДанных = ПроверяемаяСсылка.ПолучитьОбъект();

Если ОбъектДанных = Неопределено Тогда

// Записи в базе нет

КонецЕсли;

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

Способы проверки существования

Запрос с ПЕРВЫЕ 1

Самый быстрый для массовых проверок; требует знания имени таблицы метаданных

ОбщегоНазначения.СсылкаСуществует()

Удобно в типовых конфигурациях с БСП; в самописных может отсутствовать

ПолучитьОбъект() = Неопределено

Простой код, но вычитывает весь объект; подходит для единичных проверок

Проверка записи регистров и независимых данных

Для регистров сведений понятие «записан объект» работает иначе: у записи независимого регистра нет ссылки в привычном смысле. Проверка существования записи выполняется по ключу измерений — через менеджер записи или запрос:

МенеджерЗаписи = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();

МенеджерЗаписи.Валюта = Валюта;

МенеджерЗаписи.Период = ДатаКурса;

МенеджерЗаписи.Прочитать();

Если МенеджерЗаписи.Выбран() Тогда

// Запись существует в базе

КонецЕсли;

Метод Выбран() возвращает Истина, если после Прочитать() запись найдена. Для подчинённых регистров (с регистратором) проверка выполняется через набор записей с отбором по регистратору: если после чтения Количество() больше нуля, движения записаны.

Типичные ошибки при проверке записи объекта

Частая ошибка — сравнение ссылки со строкой или с Неопределено вместо вызова Пустая(). Пустая ссылка в 1С — это не NULL и не пустая строка, а особое значение конкретного ссылочного типа, поэтому корректна только штатная проверка.

Вторая распространённая ошибка — полагаться на заполненность ссылки как на гарантию существования объекта. После обменов, восстановления из копии или прямого удаления записей ссылка может указывать в никуда. Перед обращением к данным такой ссылки нужна проверка существования.

Третья ошибка — проверять ЭтоНовый() у объекта, полученного через ПолучитьОбъект() от битой ссылки: такой вызов вернёт Неопределено, и обращение к методу вызовет исключение. Сначала проверяйте результат на Неопределено.

Типичные ошибки
01
Сравнение ссылки с пустой строкой вместо Ссылка.Пустая() — проверка не работает
02
Проверка только Пустая() без проверки существования — битая ссылка проходит как валидная
03
Обращение к ПолучитьОбъект() без проверки на Неопределено — исключение при битой ссылке
04
Массовая проверка через ПолучитьОбъект() в цикле — лишняя нагрузка и замедление обработки

Практические рекомендации и выбор способа

Выбор способа зависит от контекста. Для объекта, который вы сами создаёте в коде, достаточно ЭтоНовый() или Ссылка.Пустая(). Для ссылки неизвестного происхождения нужна проверка существования запросом или функцией БСП. Для записей регистров сведений — чтение менеджером записи с проверкой Выбран().

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

Итог

Что важно запомнить

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

Часто задаваемые вопросы

Чем отличается ПустаяСсылка() от Ссылка.Пустая()?

Функция глобального контекста не используется для ссылок напрямую; у ссылочных значений применяется метод Пустая(), который возвращает Истина для незаполненной ссылки. Для проверки значения произвольного типа на пустоту есть функция ЗначениеЗаполнено() — она универсальна и работает в том числе со ссылками.

Можно ли проверить запись объекта без запроса к базе?

Для объекта, который находится у вас в памяти, да — достаточно ЭтоНовый(). Для произвольной ссылки без обращения к базе проверить существование нельзя: платформа хранит только идентификатор, а факт наличия записи выясняется чтением из базы запросом или ПолучитьОбъект().

Почему Ссылка.Номер у битой ссылки не вызывает ошибку?

При обращении к реквизиту через ссылку платформа выполняет неявный запрос. Если записи нет, возвращаются пустые значения соответствующих типов, а не исключение. Поэтому такой код «молчит», и проблему нужно выявлять явной проверкой существования.

Как проверить, записан ли набор записей регистра?

Установите отбор по регистратору (или по измерениям для независимого регистра), вызовите Прочитать() и проверьте Количество() больше нуля. Для менеджера записи независимого регистра сведений после Прочитать() используйте метод Выбран().

Что быстрее: запрос или ПолучитьОбъект()?

Для простой проверки существования запрос с конструкцией ПЕРВЫЕ 1 быстрее, так как читает минимум данных. ПолучитьОбъект() вычитывает объект целиком со всеми табличными частями. Разница особенно заметна в циклах и при работе с крупными документами.

Как обработать ситуацию, когда объект могли удалить между проверкой и записью?

В многопользовательской среде такая гонка возможна. Критичные операции выполняйте в транзакции: проверка и последующее изменение данных будут атомарны, а при конфликте блокировок платформа вызовет исключение, которое можно обработать через Попытка/Исключение.