В процессе сопровождения баз данных 1С специалисты нередко сталкиваются с ситуацией, когда в реквизитах документов или отчетах вместо наименования элемента отображается надпись вида <Объект не найден> (8:bed494de80b92fae11e43cf8abea2cda). При этом визуально в справочнике нужная позиция может присутствовать, а попытка сопоставить идентификатор с архивной копией иногда приводит к совершенно неожиданным результатам. Разберем по шагам, почему возникает эта проблема, как устроена внутренняя ссылка платформы и как восстановить ссылочную целостность информационной базы.
Проанализируем структуру строкового представления ненайденного объекта. Запись состоит из двух частей, разделенных двоеточием:
8:) — внутренний идентификатор таблицы метаданных в конкретной информационной базе. В разных базах (например, в рабочей и тестовой) этот номер может отличаться, если структура конфигурации накатывалась независимо.Важно понимать особенность платформы 1С: при хранении данных в таблицах СУБД используется специфический порядок байтов с внутренней перестановкой групп в UUID. Если взять шестнадцатеричную строку непосредственно из текста битой ссылки и передать ее в конструктор объекта УникальныйИдентификатор без учета обратного преобразования порядка байтов, платформа сформирует искаженный идентификатор. Именно поэтому при поиске в архивной базе по «сырому» коду программист находит совершенно другой, посторонний элемент либо не находит ничего.
Выясним причину, из-за которой элемент теряет связь с базой данных:
Shift + Delete или выбирает команду непосредственного удаления в списке. В этом случае платформа удаляет запись из таблицы без проверки ссылочной целостности.Удалить(): если в доработках конфигурации вместо установки пометки на удаление вызван метод Объект.Удалить(), запись физически уничтожается мгновенно, оставляя во всех связанных документах «хвосты».Если мы знаем точный шестнадцатеричный идентификатор удаленного объекта и хотим привязать к существующим битым ссылкам реальный справочник, создадим элемент программно. Для этого используется метод УстановитьСсылкуНового(), который работает исключительно для объектов, еще не записанных в информационную базу.
Рассмотрим пример кода на встроенном языке:
ИмяСправочника = "Номенклатура";
СтрGUID = "bed494de-80b9-2fae-11e4-3cf8abea2cda";
Идентификатор = Новый УникальныйИдентификатор(СтрGUID);
НоваяСсылка = Справочники[ИмяСправочника].ПолучитьСсылку(Идентификатор);
НовыйОбъект = Справочники[ИмяСправочника].СоздатьЭлемент();
НовыйОбъект.УстановитьСсылкуНового(НоваяСсылка);
НовыйОбъект.Наименование = "Восстановленный элемент";
НовыйОбъект.Записать();
После записи элемента ссылка перестанет быть битой во всех регистрах и документах. Если в базе уже был создан дубликат этого элемента под новым GUID, далее воспользуемся стандартной обработкой Поиск и удаление дублей, выбрав в качестве правильного элемента нужный объект.
Если нужный элемент уже существует в справочнике под другим идентификатором, правильнее перенаправить все места использования с «битой» ссылки на правильную. Посмотрим, как это реализовать:
УникальныйИдентификатор и функцию ПолучитьСсылку().НайтиПоСсылкам().ОбменДанными.Загрузка = Истина, чтобы обойти лишние проверки проведения и не нарушать границы запрета редактирования.Посмотрим на пример обработки:
МассивСсылок = Новый Массив;
ИдентификаторБитый = Новый УникальныйИдентификатор("bed494de-80b9-2fae-11e4-3cf8abea2cda");
БитаяСсылка = Справочники.Номенклатура.ПолучитьСсылку(ИдентификаторБитый);
МассивСсылок.Добавить(БитаяСсылка);
ТаблицаСсылок = НайтиПоСсылкам(МассивСсылок);
ПравильнаяСсылка = Справочники.Номенклатура.НайтиПоКоду("000000001");
Для Каждого Стр Из ТаблицаСсылок Цикл
ОбъектМетаданных = Стр.Метаданные;
СсылкаНаОбъект = Стр.Данные;
// Получаем объект для редактирования
Попытка
ОбъектДляИзменения = СсылкаНаОбъект.ПолучитьОбъект();
ОбъектДляИзменения.ОбменДанными.Загрузка = Истина;
// Заменяем ссылку в реквизите или строке табличной части
// в зависимости от данных из ТаблицаСсылок
ОбъектДляИзменения.Записать();
Исключение
ЗаписьЖурналаРегистрации("ЗаменаСсылок", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Когда повреждений много, эффективным решением выступает штатный инструмент конфигуратора. Разберем порядок действий:
Неопределено. Этот вариант удобен, если данные потеряли актуальность.Чтобы исключить появление надписей <Объект не найден> в будущем, применим административные и организационные меры:
Интерактивное удаление и Интерактивное удаление помеченных. Пользователь должен иметь возможность только выставить пометку на удаление.