Как определить программно ссылка битая или нет ?

1. Rudakov_D 227 29.08.12 07:24 Сейчас в теме
Здравствуйте

Нужно определить ссылка битая или нет, и не хочется использовать конструкцию попытка исключение.
Как определить программно, ссылка битая или нет ?
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
9. Поручик 4674 29.08.12 11:01 Сейчас в теме
(1) В БСП есть функция

// Проверяет физическое наличие записи в информационной базе данных о переданном значении ссылки
//
// Параметры:
//  ЛюбаяСсылка - значение любой ссылки информационной базы данных
// 
// Возвращаемое значение:
//  Истина - ссылка физически существует;
//  Ложь   - ссылка физически не существует
//
Функция СсылкаСуществует(ЛюбаяСсылка) Экспорт
	
	ТекстЗапроса = "
		|ВЫБРАТЬ
		|	Ссылка
		|ИЗ
		|	[ИмяТаблицы]
		|ГДЕ
		|	Ссылка = &Ссылка
		|";
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[ИмяТаблицы]", ИмяТаблицыПоСсылке(ЛюбаяСсылка));
	
	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("Ссылка", ЛюбаяСсылка);
	
	УстановитьПривилегированныйРежим(Истина);
	
	Возврат НЕ Запрос.Выполнить().Пустой();
	
КонецФункции
Показать
user1619761; Pigzilla; Monex; prog2019; Рамзес; hityay; FilatovRA; exclusive; syurev; user1716460; ghostaz; sumpavig; Andy_NTG; akocur; alsegor; pioneeer; jobkostya1c_ERP; simuljakr; Student1C; Gendelf; Merkalov; vv2; LordKim; Lacoste4life; RomanKod; Sarkikker; Andrei_Ivanov; houpl; user1232941; Fales; v3n7; unknown181538; GonziK_KIV; malikov_pro; Jivchic; ram3; TeMochkiN; maxunov95; improg; kimskiysanya; mickey.1cx; Batman; zfr475; user659168_xec8787; anchovy; 7OH; treedo; McLer; Alien_job; 1v7; rusmil; adhocprog; serezhenko; Gladkov_Anton; azazana; gaspard; alex-l19041; Патриот; Kesak; HEKPOH; Dr.ZIG; pintov; +62 Ответить
10. nodalt 9 29.08.12 11:13 Сейчас в теме
(9) Вопрос ... ИмяТаблицыПоСсылке(ЛюбаяСсылка) - это что за функция? Каким образом она возвращает имя таблицы? Это же не встроенная процедура или функция.
11. ksb 29.08.12 11:15 Сейчас в теме
(10) nodalt,


// Возвращает полное имя объекта метаданных по переданному значению ссылки
// Например,
//  "Справочник.Номенклатура";
//  "Документ.ПриходнаяНакладная"
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - значение ссылки, для которого необходимо получить имя таблицы ИБ
// 
// Возвращаемое значение:
//  Строка - полное имя объекта метаданных для указанного значения ссылки
//
Функция ИмяТаблицыПоСсылке(Ссылка) Экспорт
	
	Возврат Метаданные.НайтиПоТипу(ТипЗнч(Ссылка)).ПолноеИмя();
	
КонецФункции

Показать
user1619761; Monex; user1716460; sumpavig; jobkostya1c_ERP; RomanKod; maxunov95; zfr475; drygina; McLer; 1v7; adhocprog; rayastar; Патриот; nodalt; +15 Ответить
29. improg 576 31.08.19 12:20 Сейчас в теме
(9) Да быстрее чем получитьОбъект().
2. Ntari 29.08.12 07:34 Сейчас в теме
если ссылка.ПолучитьОбъект()=неопределено тогда
simuljakr; RomanKod; Meson; vlm88; olololeg; Rustavelli; Hamsik; Восьмой; adhocprog; +9 Ответить
3. Rudakov_D 227 29.08.12 07:34 Сейчас в теме
Похоже ничего лучше чем

Если БИТАЯССЫЛКА.ПолучитьОбъект() = Неопределено тогда

уже не найти...
chemezov; RomanKod; +2 Ответить
5. Ntari 29.08.12 07:51 Сейчас в теме
(3) Arch_1,
<quote>
Похоже ничего лучше чем

Если БИТАЯССЫЛКА.ПолучитьОбъект() = Неопределено тогда

уже не найти...
</quote>
в любом случае, чтобы определить битая ссылка или нет необходимо попытаться "пройти" по этой ссылке
4. ksb 29.08.12 07:35 Сейчас в теме
Думаю как вариант банально анализировать представление формируемое платформой 1С

	Ссылка = Реквизит1.Родитель;
	
	Если Найти(Строка(Ссылка), "<Объект не найден> (" ) <> 0 тогда 
		Сообщить("Ссылка битая");
	Иначе 
		Сообщить("Ссылка НЕ битая");
	КонецЕсли;	
Показать
simuljakr; DoctorRoot; magiceagle; user1502168; adhocprog; _OVEN_; pbahushevich; +7 1 Ответить
13. for_sale 971 14.10.16 20:43 Сейчас в теме
(4) ksb, just for lulz:

НовЭл = Справочники.Справочник.СоздатьЭлемент();
НовЭл.Наименование = "Сейчас мы <Объект не найден> ( поломаем систему";
НовЭл.Записать();

Ссылка = НовЭл.Ссылка;
    
Если Найти(Строка(Ссылка), "<Объект не найден> (" ) <> 0 тогда 
    Сообщить("Ссылка битая");
Иначе 
    Сообщить("Эта ветка нам не понадобится, можно её удалить");
КонецЕсли;
Показать
st8899; Lacoste4life; TreeDogNight; Brawler; leaguener; CnupT; fst; CyberCerber; 7OH; adhocprog; temdj; +11 2 Ответить
15. &rew 49 05.11.16 21:11 Сейчас в теме
(13) Блин, хоть ветка старая, но... Чуваки и чувихи, которые ищут объекты не найденные скорее всего это делают относительно не часто, и вряд ли им попадется маньяк, который так будет делать. Понимаю что учитывать надо, но ровно с той же вероятностью, даже кстати меньшей, чем то что конфа будет в режиме совместимости с 8.3.5 и ниже. "Найти" там, вся фигня...
user1619761; user1951539; sinichenko_alex; insurgut; +4 Ответить
42. MegasXXX 3 02.11.22 18:47 Сейчас в теме
(4)
Найти дольше чем простейшее, для документов:
Лев(Ссылка, 1)  = "<"

Для справочников лучше брать больше 1 символа, вдруг кто наименование напишет "<Товар>"
43. user1863362 02.11.22 20:35 Сейчас в теме
(42) Открой уже для себя существование ОбработкаПолученияПредставления для того же документа. После открытия подумай еще раз над своим предложением.
6. Rudakov_D 227 29.08.12 08:22 Сейчас в теме
Еще есть вариант запроса, и он будет вероятно быстрее работать...
7. Ntari 29.08.12 09:03 Сейчас в теме
(6) Arch_1,
<quote>
Еще есть вариант запроса, и он будет вероятно быстрее работать...
</quote>
наврядли..одинаково отработают. но запрос или ПолучитьОБъект() это уже на выбор автора))
8. andrewks 1370 29.08.12 10:54 Сейчас в теме
(7) AntonBaikal,
наврядли..одинаково отработают


не думаю. попробуйте считать большой документ с кучей реквизитов и данных в ТЧ, а затем сравните с запросом
12. Ntari 29.08.12 11:28 Сейчас в теме
(8) andrewks, про документы как то не подумал)
22. Hobbit_Jedi 13.11.17 16:56 Сейчас в теме
(12) Простите, что "оживляю" мертвую ветку.
Только что наступил на еще одну граблю в пользу запроса (из функции СсылкаСуществует) против Ссылка.ПолучитьОбъект() = Неопределено.
Получение объекта, кроме зачитывания из БД кучи табличных частей и движений документа, еще и выполняет код инициализации модуля объекта... А некоторые доброжелатели (из разработчиков типовых конфигураций) там ТАКИХ сюрпризов наоставлять могут, что вся производительность в ноль уйдет.
user1951539; Windsor77; TreeDogNight; hawkmax; jobkostya1c_ERP; +5 1 Ответить
14. maks_20 164 21.10.16 19:57 Сейчас в теме
В запросе условием что-то типа такого: Где Номенклатура.Ссылка ЕСТЬ NULL
16. EMelihoff 07.11.16 12:40 Сейчас в теме
Я ищу запросом:
Ссылка.Код IS NULL
rad1st; kivals; kokstik; +3 Ответить
17. PlatonStepan 38 09.11.16 18:59 Сейчас в теме
Извиняюсь за некропост, но с некоторой версии платформы появился встроенный реквизит ссылочного объекта "ВерсияДанных", который заполняется системой в момент записи объекта. Значит если объекта нет, то это значение будет не заполнено.

ЭтоБитаяСсылка = ПустаяСтрока(Ссылка.ВерсияДанных);

FuJluH; Igor_Ryaboff; kladovoy; user892471; kabantus; marku; pvlunegov; TreeDogNight; zhuntovda; Jivchic; anchovy; Enya_06; falsepilot; +13 Ответить
18. корум 287 10.11.16 10:12 Сейчас в теме
(17) некро это полгода, год, три... :)
19. for_sale 971 05.12.16 14:51 Сейчас в теме
(17), с тем же успехом можно проверить любой другой реквизит Ссылки.

И ПустаяСтрока - это не комильфо, НЕ ЗначениеЗаполнено работает быстрее.
20. fromtomike 48 05.12.16 15:27 Сейчас в теме
А почему не так ?

Для документа: 
Если СокрЛП(Ссылка.Номер) = "" Тогда
...
КонецЕсли;

Для справочника (если длина кода в конфигураторе <> 0): 
Если СокрЛП(Ссылка.Номер) = "" Тогда
...
КонецЕсли;
Показать
23. Hobbit_Jedi 13.11.17 22:21 Сейчас в теме
(20) Замеры показывают, что Ссылка.ВерсияДанных, Ссылка.Номер, Ссылка.ЛюбойРеквизит - выполняются по времени соизмеримо с Ссылка.ПолучитьОбъект().
И это правильно, т.к. если вспоминать мат. часть, то выяснится, что для получения реквизита через точку, платформа зачитывает в память весь объект, со всеми табличными частями и движениями (если это документ), и получает от него реквизит. И кстати, сам объект какое-то время висит в кэш-памяти - на случай, если надо будет от него через точку еще какие-нибудь реквизиты получать.
Посему вывод: функция СсылкаСуществует - самый быстрый способ проверки (особенно если еще и саму функцию в кэшируемый модуль поместить).
kirinalex; PlatonStepan; +2 1 Ответить
21. aap290680 05.12.16 15:45 Сейчас в теме
в запросе однозначно лучше всего и проверено, например проверить документы с битой ссылкой на контрагент: Документ.Контрагент.Ссылка ЕСТЬ NULL обязательно надо добавлять .Ссылка чтобы там NULL получился у битой ссылке.
24. jobkostya1c_ERP 100 09.01.18 09:56 Сейчас в теме
А не подскажете как проверить что по COM-соединению битая ссылка? Чтоб оптимально было. Столкнулся например что группа справочника в базе-источнике это битая ссылка
25. Xershi 1486 09.01.18 10:13 Сейчас в теме
(24) запросом в стиле ком.
jobkostya1c_ERP; +1 Ответить
26. jobkostya1c_ERP 100 09.01.18 10:22 Сейчас в теме
(25)Спасибо, туплю в первый день. Там же и проверять по КОМ.
27. Омский Домовой 408 25.08.19 22:03 Сейчас в теме
Как выяснилось эксперементальным путем для проверки на "Объект не найден" быстрее работает конструкция
Отказ = СтрНайти(Строка(БитаяСсылка),"<Объект не найден>") > 0;

нежели
Отказ = БитаяСсылка.ПолучитьОбъект() = Неопределено;


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

Через COM такой подход тоже будет работать только типа
СтрНайти(Соединение.Строка(БитаяСсылка),"<Объект не найден>")
ANF-BR; user686589_sev_s; +2 Ответить
28. Xershi 1486 25.08.19 22:16 Сейчас в теме
(27) конечно быстрее. Получить объект это тяжелая операция, а сравнение строки легкая. Но тяжелая операция гарантированный результат. А поиск по строке с вероятностью не даст результат. Как поломать этот алгоритм уже писали.
pvlunegov; +1 Ответить
37. ANF-BR 05.09.22 06:50 Сейчас в теме
(27)
Отказ = СтрНайти(Строка(БитаяСсылка),"<Объект не найден>") > 0;


Спасибо! Помогло!
38. SlavaKron 05.09.22 10:47 Сейчас в теме
(37) Это не самое оптимальное решение.
Очевидно же, что единственный нативный способ проверить существование объекта – это запрос:
Запрос = Новый Запрос("ВЫБРАТЬ NULL ИЗ Справочник.МойСправочник ГДЕ Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", БитаяСсылка);
СсылкаБитая = Запрос.Выполнить().Пустой();
Ничего быстрее вы не придумаете.
40. ANF-BR 05.09.22 13:21 Сейчас в теме
(39)
(38)
Мне кажется простое сравнение строки гораздо быстрее любой выборки, ну ладно, попробую ради эксперимента
41. Fox-trot 158 05.09.22 14:52 Сейчас в теме
(40) таки да, но ведь в нашем случае сравнение не "простое"
39. Fox-trot 158 05.09.22 12:31 Сейчас в теме
30. mialord 18.03.20 18:50 Сейчас в теме
Если ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Документ, "Ссылка") = Неопределено Тогда // сгенерирована ссылка без описания объекта
	ТекстСообщения = СтрШаблон(НСтр("ru = 'Не обработана строка фабрики XDTO ReturnFlow:
                                     |Не обнаружена заявка на закупку с идентификатором %1'"), UUID);
	ВызватьИсключение ТекстСообщения;
КонецЕсли;
31. user645820_victor80vh 05.06.20 00:41 Сейчас в теме
// Проверка существует ли объект по ссылке
Функция СсылкаСуществует(СсылкаНаОбъект)
	
	Запрос = Новый Запрос("Выбрать Таб.Ссылка ИЗ "+СтрЗаменить(СериализаторXDTO.XMLТипЗнч(СсылкаНаОбъект).ИмяТипа,"Ref.",".") +" КАК Таб ГДЕ Таб.Ссылка = &СсылкаНаОбъект");
	Запрос.УстановитьПараметр("СсылкаНаОбъект", СсылкаНаОбъект);
	Результат = Запрос.Выполнить();
	Возврат НЕ Результат.Пустой();
	
КонецФункции
Показать
vv2; japopov; akkorn; +3 Ответить
33. akkorn 23.07.21 09:37 Сейчас в теме
(31)
Запрос = Новый Запрос("Выбрать Таб.Ссылка ИЗ "+СтрЗаменить(СериализаторXDTO.XMLТипЗнч(СсылкаНаОбъект).ИмяТипа,"Ref.",".") +" КАК Таб ГДЕ Таб.Ссылка = &СсылкаНаОбъект");


Совершенно согласен с подходом. Поясню.
Здесь много говорили о производительности. И запросом ссылку проверять быстрее и правильнее, не загружая объект в память.
Однако, ни кто не обратил внимание на составную функции СсылкаСуществует()
Там используется другая функция ИмяТаблицыПоСсылке(), которая берет Метаданные() объекта.

Замерил, - это примерно 10 раз медленнее чем XMLТипЗнч() (на цикле в 10000).
Проверить может каждый. Замер времени делал просто - обернул код вызова ТекущаяУниверсальнаяДатаВМиллисекундах() и узнал разницу.

Да, XMLТипЗнч() изменяет описание объекта. Вместо "Справочник.Номенклатура" она возвращает "CatalogRef.Номенклатура", поэтому приходится использовать дополнительно СтрЗаменить(). Для запроса не играет роли как мы обзываем тип объекта, - "Catalog." или "Справочник.".

Поэтому переписал функцию. Мне же потом и пригодится. Помещу здесь новый вариант:

&НаСервере
Функция СсылкаСуществует(ЛюбаяСсылка) Экспорт
	//ИмяТаблицы = Метаданные.НайтиПоТипу(ТипЗнч(ЛюбаяСсылка)).ПолноеИмя(); // взять Метаданные() в 10 раз медленнее чем XMLТипЗнч(..)
	ИмяТаблицы = СтрЗаменить(СериализаторXDTO.XMLТипЗнч(ЛюбаяСсылка).ИмяТипа, "Ref.", ".");
	
	ТекстЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка ИЗ [ИмяТаблицы] ГДЕ Ссылка = &Ссылка";
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[ИмяТаблицы]", ИмяТаблицы);
	
	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("Ссылка", ЛюбаяСсылка);
	
	УстановитьПривилегированныйРежим(Истина);
	Результ = НЕ Запрос.Выполнить().Пустой();
	УстановитьПривилегированныйРежим(Ложь);
	Возврат Результ;
КонецФункции
Показать
zlexuzz; evgaid; vv2; AndrewKop; mc1c; salbey; user1233797; eufes; EvgeTrofi; japopov; +10 Ответить
35. vlhown 28.09.21 11:38 Сейчас в теме
(31) Проверил. На 1000 запусков проверка ссылки через метаданные занимает 2,647658 секунд, проверка через сериализатор - 2,562312 секунд.
Выигрыш - 3%. Никак не "примерно 10 раз медленнее".
Прикрепленные файлы:
user1035175; +1 Ответить
36. Sashares 34 28.09.21 12:27 Сейчас в теме
(35) Если надо проверить 1000 ссылок одного типа, это можно сделать одним запросом, а не 1000 запросами. Ну так, к слову =)
32. user645820_victor80vh 05.06.20 00:42 Сейчас в теме
В запросах можно вычислить если соединить с таблицей Ссылки и отсеять по значению NULL
34. пользователь 20.08.21 09:50
Сообщение было скрыто модератором.
...
44. PlatonStepan 38 26.04.23 06:49 Сейчас в теме
И снова: -Здравствуйте!

Предлагаю рассмотреть ещё один вариант определения существования объекта по ссылке - через наличие представления навигационной ссылки.
Не могу сказать, что он 100% корректный, так как если у некоторых объектов представлением будет "", то он не применим.

Функция ПолучитьПризнакСуществуетОбъектСсылки(Ссылка)
	массивНС = новый массив(1);
	
	УстановитьПривилегированныйРежим(Истина);
	
	массивНС[0] = ПолучитьНавигационнуюСсылку(Ссылка);
	Возврат ПолучитьПредставленияНавигационныхСсылок(массивНС)[0].Текст <> "";
КонецФункции


В прикрепленной обработке есть тест на 2000 итераций, а также функция пакетной проверки ПолучитьМассивСуществующихОбъектовСсылок(массивСсылок)

Результаты замеров на 2000 итераций:
БСПшный СсылкаСуществует(): 12.683;
ПолучитьПризнакСуществуетОбъектСсылки(Ссылка): 7.251;
ПолучитьМассивСуществующихОбъектовСсылок(массивСсылок): 1.830;

Если посмотреть на объект ПредставлениеНавигационнойСсылки, то с 8.3.13 у него есть метод Представление():
Для корректных ссылок возвращает - значение свойства Текст.
Для некорректных ссылок (ссылка неправильно сформирована, объект отсутствует в базе, объект метаданных отсутствует, или у пользователя нет права на объект) - значение свойства НавигационнаяСсылка.

Получается можно также сравнивать эти свойства с результатом этого метода, для определения существования объекта
Прикрепленные файлы:
ВнешняяОбработка_ПолучениеНавигационныхСсылокТест.epf
45. SlavaKron 26.04.23 14:59 Сейчас в теме
(44) Некорректное сравнение: либо мы сравниваем алгоритмы существования одиночной ссылки, либо массива ссылок, – это разные алгоритмы.
46. PlatonStepan 38 27.04.23 06:12 Сейчас в теме
(45)
Результаты замера по массиву ссылок привёл только для демонстрации возможности и отражения разницы.
Кстати, проверил выполнение на серверной стороне, 1000 итераций :
Проверка через запрос к таблице ~ 1200мс;
Проверка через представления навигационной ссылки ~ 900мс;

Кстати стандартное представление ссылок с пустым наименованием "<>", таким образом условие проверки Текст <> "" будет работать*.
-----
*До тех пор, пока кто-то не "сломает" процедуру ОбработкаПолученияПредставления() в модуле менеджера метаданных. XD
47. SlavaKron 28.04.23 19:44 Сейчас в теме
(46) Вы тестируете в режиме обычного приложения, там код выполняется на клиенте, пока не доходит до строк, требующих обращение к серверу, поэтому эксперимент не чистый. Проведите свои замеры в общем модуле с галками Сервер и ВызовСервера на клиент-серверной базе – результаты будут другие: чистый запрос будет стабильно быстрее, хотя и не значительно.
Либо протестируйте приложенную обработку на управляемых формах (тонкий клиент), там можно четко контролировать контекст выполнения.
Прикрепленные файлы:
ПроверкаБыстродействияОпределенияБитойСсылки.epf
PlatonStepan; +1 Ответить
48. PlatonStepan 38 02.05.23 11:43 Сейчас в теме
(47)
Согласен, нет ничего надёжнее и быстрее, чем обращение непосредственно к данным СУБД.

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

Однако на другом сервере 1С/СУБД, где не включен debug и который пошустрее, запросом значительно быстрее (x2).

Из этого делаю вывод, что чем меньше операций на "голом" 1С, тем лучше :)

По сути ПолучитьПредставленияНавигационныхСсылок() выполняет тот же запрос к таблице с искомыми ссылками, но при этом дополнительно вызывает обработчик функции ПРЕДСТАВЛЕНИЕ().
49. klmsoft 19 27.03.24 13:45 Сейчас в теме
Простой пример поиска битых ссылок справочника "Номенклатура" во всех документах базы с табличной частью "Товары" за период.
Битая ссылка выводиться как GUID c которым дальше разбираемся как нам надо. Например - ищем в другой базе.

Запрос = Новый Запрос;
ТекстЗапроса = "";
 Для Каждого Вид Из Метаданные.Документы Цикл 
	 ТоварыТЧ =  Вид.ТабличныеЧасти.Найти("Товары");
	 Если ТоварыТЧ <> Неопределено  Тогда
		 Если ТоварыТЧ.Реквизиты.Найти("Номенклатура") <> Неопределено Тогда
			 Если ТекстЗапроса <> "" Тогда
				 ТекстЗапроса=ТекстЗапроса+"
				 |ОБЪЕДИНИТЬ ";
			 КонецЕсли;         
			 ТекстЗапроса = ТекстЗапроса+"
			 |ВЫБРАТЬ РАЗЛИЧНЫЕ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(" + Вид.Имя + "Товары.Номенклатура) КАК GUID   
			 |ИЗ Документ."+ Вид.Имя + ".Товары КАК " + Вид.Имя + "Товары ГДЕ 
			 | " + Вид.Имя + "Товары.Ссылка.Дата МЕЖДУ &ДатаНачала И &ДатаКонца   
			 | И " + Вид.Имя + "Товары.Номенклатура.Ссылка ЕСТЬ NULL";
		 КонецЕсли;  
	 КонецЕсли; 
 КонецЦикла; 
   
Показать
50. asoft65 24.04.24 06:09 Сейчас в теме
(9) Спасибо большое, Сергей - помогло и работает быстро. Вот уж не думал, что из битой ссылки 1С может извлечь имяТаблицы. Оказалось - может.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот