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