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