Как узнать, является значение ссылочного типа «битой ссылкой» или нет?

28.02.13

Разработка - Механизмы платформы 1С

Для платформ 1С-7.7 и 1С-8.x описаны простые способы выяснения того, является ли ссылочное значение ссылкой на несуществующий объект.  Для обеих платформ выложены примеры реализации функции IsEmpty(), возвращающей признак пустого значения и флаг «битой ссылки».

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Примеры
.rar 1,97Kb
23
23 Скачать (1 SM) Купить за 1 850 руб.

В некоторых случаях бывает полезным понять, является ли значение ссылочного типа «битой ссылки» (ссылкой на не существующий объект в базе) или нет.
В первую очередь это может понадобиться для обработки исключительных ситуаций, что бы выводить пользователю более внятные сообщения,
чем это делает сама платформа. Например, не имеет смысла записывать, удалять или открывать форму несуществующего объекта.

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

Предлагаю простые решения этой задачи (без построения запросов к базе данных), полученные эмпирическим путём:

1) Для платформы 1С-7.7:
      -   Для «битой» ссылки метод Ссылка.Выбран() и функция ПустоеЗначение() возвращают ноль;
      -   Для «пустой» ссылки метод Ссылка.Выбран() возвращает ноль, а функция ПустоеЗначение()  единицу;
      -   Для «нормальной» ссылки метод Ссылка.Выбран() возвращает единицу, а функция ПустоеЗначение()  ноль;

 

     Таким образом, с точки зрения 1С-7.7 «битая» ссылка – это не пустое значение, которое не является выбранным.

2) Для платформы 1С-8.x:
     Все обстаит несколько сложней. 
     В обоих случаях (для «битых» и «нормальных» ссылок) метод Ссылка.Пустая() и функция ЗначениеЗаполнено() ведут себя одинаково:
     первый возвращает Ложь, а второй Истина.

 

     Простоте решение было найдено случайно, при отладке ошибок времени исполнения:

     -   Для «битой» ссылки метод Ссылка.ПолучитьОбъект() возвращает значение Неопределено;
     -   Для «пустой» ссылки» метод Ссылка.ПолучитьОбъект() выбрасывает исключение:
                                                  «Ошибка при вызове метода контекста (ПолучитьОбъект): Элемент не выбран!»;
     -   Для «нормальной» ссылки метод Ссылка.ПолучитьОбъект() возвращает значение согласно документации;

     Таким образом, с точки зрения 1С-8.х «битая» ссылка – это не пустое значение ссылочного типа,
                                                                               для которого возвращается значение объекта равное Неопределено
.
 

При этом особняком стоят ссылки на значения перечислений. У них нет метода Ссылка.ПолучитьОбъект().
И трудно вообще представить себе ситуацию, когда ссылка на перечисление может оказаться «битой».
Например, если удалить значение в конфигураторе, то при восстановлении значения функцией ЗначениеИзФайла() возвращается пустая ссылка.
Поэтому будем считать любые ссылки на перечисления «небитыми».

В архиве файла поставки находятся текстовые файлы с примерами реализации функции IsEmpty() для платформ 1С-7.7 и 1С-8.x,
возвращающей признак пустого значения и флаг «битой ссылки» для произвольного значения. 

См. также

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    7451    bayselonarrend    20    

154

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    5943    dsdred    16    

80

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    17672    YA_418728146    26    

71

Перенос данных 1C Механизмы платформы 1С Системный администратор Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    11224    dsdred    44    

130

Механизмы платформы 1С Программист Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    23761    SeiOkami    48    

135

Механизмы платформы 1С Системный администратор Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    18831    human_new    27    

80

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14732    YA_418728146    7    

166
Отзывы
21. pakill 43 03.07.15 16:07 Сейчас в теме
Есть еще и такой способ:


Если ЗначениеЗаполнено(Ссылка) Тогда
    Если ЗначениеЗаполнено(Ссылка.ВерсияДанных) Тогда
        Сообщить("Живая ссылка");
    Иначе
        Сообщить("Битая ссылка");
    КонецЕсли
Иначе
    Сообщить("Пустая ссылка");
КонецЕсли;
Показать
pridecom; jan-pechka; texnic79; Raf_f; begemot; Bunny; escape; Nicholas; SoulPower; Drivingblind; Babylka; yuraos; user631966_482672; EMelihoff; +14 Ответить
Остальные комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. yuraos 1003 28.02.13 09:49 Сейчас в теме
Всем доброе время суток!
Небольшое замечание по функции IsEmpty(), что в файлах поставки.

Функция имеет следующий синтаксис:

// Старая добрая функция ПустоеЗначение() из 1С77:
// проверка значения на "пустое" ++ дополнительные возможности
// СостояниеСсылки: -1 (нет объекта); 0 (пустая ссылка); +1 (есть объект); Null (значение - не ссылка)
Функция IsEmpty(Значение, ПоПустомуСодержанию = Истина, СостояниеСсылки = Null) Экспорт

Аргумент ПоПустомуЗначению определяет, считать ли пустым значение с "пустым содержанием":
- Для строк, если они состоят из не "значящих" символов;
- Для ссылок, если они "битая";
- Для таблиц и деревьев значений, если в нет строк, но есть колонки;

Через аргумент СостояниеСсылки возвращается признак,
определяющий является ли проверяемое значение ссылкой или нет.
Если да - то является она битой ссылкой или нет, согласно описанию в комментариях.
2. Serj1C 483 28.02.13 10:08 Сейчас в теме
Как-то негуманно проверять битость ссылок через получение объекта да еще и в попытке.
Также можно просто проверить ссылку приведением к строке и поиском в ней (найти(Ссылка, "<Объект не найден")>0), но это кривота, т.к. если запуститься на другом языке, то, наверняка представление будет другим.

Мне нравится проверять запросом:
Выбрать Спр.Наименование Из Справочник.Номенклатура как Спр Где Ссылка=&Ссылка


Если результат запроса будет пустым - то ссылка - битая.
4. Darth_Anyan 28.02.13 12:13 Сейчас в теме
(2) Serj1C,
а лучше не наименование, а пометку удаления проверять... тогда будет универсальный запросик для справочников и документов, только имя таблицы подставить.
7. yuraos 1003 28.02.13 20:35 Сейчас в теме
(2) Serj1C,
Как говорит мой ОДМИН - ЗАЧОТ !!!
ты открыл новый способ создания битых ссылок в базе.
ввел номенклатуру с наименованием ""<Объект не найден>""
и вот тебе она - проклятая!!!
:)
ShantinTD; +1 Ответить
3. yandextesting 148 28.02.13 12:12 Сейчас в теме
Функция, позволяющая быстро определить битая ссылка или нет:

Функция ОбъектБДСуществует(ТестоваяСсылка) Экспорт

    МД = Метаданные.НайтиПоТипу(ТипЗнч(ТестоваяСсылка));
    ИмяОбъекта = МД.Имя;
    ПолноеИмяОбъекта = МД.ПолноеИмя();

    Запрос = новый Запрос();
    Запрос.Текст =
    "ВЫБРАТЬ
    |   ИСТИНА КАК СсылкаБДСуществует
    |ИЗ
    |   " + ПолноеИмяОбъекта + " КАК " + ИмяОбъекта + "
    |ГДЕ
    |   " + ИмяОбъекта + ".Ссылка = &Cсылка";
    Запрос.УстановитьПараметр("Cсылка", ТестоваяСсылка);
    РезультатЗапроса = Запрос.Выполнить();

    Возврат Не РезультатЗапроса.Пустой();

КонецФункции
Показать
yuraos; w-divin; +2 Ответить
8. yuraos 1003 28.02.13 20:41 Сейчас в теме
(3) yandextesting,
твой пример не совсем решает задачу поставленную в статье.
он не позволяет отличить пустую ссылку от битой.
для обеих ссылки не существуют объекты в базе.
но первая является специальным значением, означающим не выбранное значение ссылочного типа.
а вторая же является реальной ссылкой на объект, который был удален ... ну или еще не создан.
:)
9. yuraos 1003 28.02.13 20:54 Сейчас в теме
(8)
Тем не менее я решил взять твой вариант за основу.
и сравнить ее с моим вариантом в тестовой обработке (смотри вложение к посту).
для этого я его немного подправил, чтобы оба варианта возвращали одно и тоже.
---

Функция ОбъектНЕСуществует0(ТестоваяСсылка,СтатусСсылки) Экспорт
	Если ТестоваяСсылка=Неопределено Тогда
		СтатусСсылки = Null;
		Возврат Истина;
	КонецЕсли;
	Если ТестоваяСсылка.Пустая() Тогда
		СтатусСсылки = 0;
		Возврат Истина;
	Иначе
	    СтатусСсылки = ?(ТестоваяСсылка.ПолучитьОбъект() = Неопределено,-1,1); 
		Возврат (СтатусСсылки = -1);
	КонецЕсли;
КонецФункции

Функция ОбъектНЕСуществует1(ТестоваяСсылка,СтатусСсылки) Экспорт
	Если ТестоваяСсылка=Неопределено Тогда
		СтатусСсылки = Null;
		Возврат Истина;
	КонецЕсли; 
	Если ТестоваяСсылка.Пустая() Тогда
		СтатусСсылки = 0;
		Возврат Истина;
	Иначе
	    МД = Метаданные.НайтиПоТипу(ТипЗнч(ТестоваяСсылка));
	    ИмяОбъекта = МД.Имя;
	    ПолноеИмяОбъекта = МД.ПолноеИмя();
	    Запрос = Новый Запрос();
	    Запрос.Текст =
	    "ВЫБРАТЬ
	    |   NULL КАК Ничто
	    |ИЗ
	    |   " + ПолноеИмяОбъекта + " КАК " + ИмяОбъекта + "
	    |ГДЕ
	    |   " + ИмяОбъекта + ".Ссылка = &Cсылка";
	    Запрос.УстановитьПараметр("Cсылка", ТестоваяСсылка);
	    РезультатЗапроса = Запрос.Выполнить();
	    NotExist = НЕ РезультатЗапроса.Пустой();
	    СтатусСсылки = ?(NotExist,-1,1); 
	КонецЕсли;
	Возврат NotExist;
КонецФункции


Показать

---
результаты тестирования показали,
что покрайней мере по времени выполнения оба варианта примерно одинаковы.
обе функции выполняются где-то 15-16 msec (смотри скриншоты).
Прикрепленные файлы:
БудуБить!.rar
10. yuraos 1003 28.02.13 21:00 Сейчас в теме
(9)
Сразу предвижу довод,
что с точки зрения использования ресурсов создание объекта более затратно.
возмозможно ... хоть это и труднее проверить.
но для разовой проверки, думаю это не существенно.
--
ну а для проверки для списка в цикле, безусловно,
все нужные данные лутше расчитывать в запросе сразу для всего списка.
11. yuraos 1003 28.02.13 21:04 Сейчас в теме
(9)
как видно мой вариант несколько компакней
...
а если результат одинаковый - зачем кодить больше.
:)
12. yandextesting 148 01.03.13 23:19 Сейчас в теме
(11) мой вариант предпочтительнее использовать при проверке большого количества ссылок в цикле или идущих потоком, например, при загрузке данных, экономится значительный объем времени.
13. yuraos 1003 02.03.13 07:08 Сейчас в теме
(12)
yandextesting,
(10)

ну а для проверки для списка в цикле, безусловно,
все нужные данные лутше расчитывать в запросе сразу для всего списка.

вызов функции в цикле обработки
ни мой ни в твоем варианте не являются "оптимальными"
с точки общих рекомедаций разработки...
:)
14. yandextesting 148 02.03.13 23:12 Сейчас в теме
(13) тем не менее, мне на практике приходилось сталкиваться с необходимостью выполнения таких проверок именно в таком виде, когда заведомо невозможно получить перечень всех ссылок, чтобы загнать их в один запрос или пакет запросов для выполнения сразу массовой проверки. Так что не всегда и везде возможно выполнять рекоммендации, да и разработчики 1С сами иногда непрочь "погрешить" в своем коде:-)
15. yuraos 1003 04.03.13 20:20 Сейчас в теме
(14) ну чтож, yandextesting,
истины ради провел еще одно тестирование для имитации обработки в цикле списка ссылок.
результаты довольно любопытны
(смотри скриншоты, модифицированная тестовая обработка - во вложении).
---
мой вариант в случае "нормальной" ссылки раза в 4 лутше, а в случае "битой" - раза в 2.5 хуже.

PS
и если "битые" ссылки встречаются не так часто...
:)
Прикрепленные файлы:
БудуБить!-2.epf
yandextesting; +1 Ответить
16. yandextesting 148 05.03.13 10:09 Сейчас в теме
(15) хм... интересно :) я в свое время эту тему на Мисте поднимал ( http://www.forum.mista.ru/topic.php?id=423487 ) под ником maxp77. Так вот, если память мне не изменяет, то на простых объектах (типа справочника, имеющего только код и наименование без кучи табличных частей и реквизитов) определение битой ссылки методом "
Ссылка.ПолучитьОбъект()
" будет отрабатывать по времени сопоставимом с определением ее "битости", указанным мною методом, а вот на бОльших объектах, имеющих несколько табличных частей с десятком реквизитов в каждой (а бывает и под сотню встречаются народные поделки), моя метода в цикле будет отрабатывать значительно быстрее.
20. zqzq 25 29.07.13 09:35 Сейчас в теме
(15)
Некорректная проверка... Нужно проверять для разных ссылок, а не одну и ту же 10000 раз, т.к. ПолучитьОбъект() кэширует результат в оперативную память на некоторое время (а также считывает из базы все реквизиты и табличные части, что абсолютно лишне).
KAPACEB.AA; +1 Ответить
5. i132 123 28.02.13 12:57 Сейчас в теме
в 8.2 у пустой ссылки Строка(Ссылка.УникальныйИдентификатор())="00000000-0000-0000-0000-000000000000"
у битой ссылки будут какие-то цифры-буквы
6. yuraos 1003 28.02.13 18:26 Сейчас в теме

в 8.2 у пустой ссылки Строка(Ссылка.УникальныйИдентификатор())="00000000-0000-0000-0000-000000000000"
у битой ссылки будут какие-то цифры-буквы

в том то и проблемма, что у битой ссылки и у не битой не пустой ссылки
в ГУИД-е "будут какие-то цифры-буквы".
А вот какая из них "битая" - ???
---
ЗЫ:
а пустую ссылку проще проверить по условию
Ссылка.Пустая() = Истина
без заморочек с ГУИД-ом.
:)
17. margo_m09 28.03.13 07:10 Сейчас в теме
хорошая идея, сразу понравилась обработка, даже если и есть какие недочеты пока при использовании, не заметили))))
18. yuraos 1003 28.03.13 09:29 Сейчас в теме
(17) margo_m09,
мы с тобой как близнецы братья...
...только глаза разного цвета.
:)
19. margo_m09 28.03.13 10:17 Сейчас в теме
21. pakill 43 03.07.15 16:07 Сейчас в теме
Есть еще и такой способ:


Если ЗначениеЗаполнено(Ссылка) Тогда
    Если ЗначениеЗаполнено(Ссылка.ВерсияДанных) Тогда
        Сообщить("Живая ссылка");
    Иначе
        Сообщить("Битая ссылка");
    КонецЕсли
Иначе
    Сообщить("Пустая ссылка");
КонецЕсли;
Показать
pridecom; jan-pechka; texnic79; Raf_f; begemot; Bunny; escape; Nicholas; SoulPower; Drivingblind; Babylka; yuraos; user631966_482672; EMelihoff; +14 Ответить
22. user631966_482672 18.01.19 16:35 Сейчас в теме
(21)

БитаяСсылка = ЗначениеЗаполнено(Ссылка) и СокрЛП(Ссылка.ВерсияДанных)=""
23. yuraos 1003 18.01.19 17:01 Сейчас в теме
(21) (22)
Годится начиная с версии платформы 8.2.?.?
Под 8.1 не работает. - у ссылок там нет свойства "ВерсияДанных"
24. user631966_482672 18.01.19 17:16 Сейчас в теме
25. Гость 01.03.23 08:18
!7777777.txt
Прикрепленные файлы:
!7777777.txt
Оставьте свое сообщение