В практике интеграции и обмена данными в среде 1С:Предприятие часто возникает ситуация, когда в распоряжении разработчика оказывается только текстовое представление уникального идентификатора (GUID/UUID), но при этом отсутствует информация о том, к какому справочнику, документу или иному объекту метаданных он относится. Рассмотрим подробнее, почему возникает эта проблема и какими способами ее можно решить, проанализируем различные подходы — от правильной организации выгрузки до методов «принудительного» поиска в существующей базе.
В системе 1С уникальный идентификатор (объект УникальныйИдентификатор) представляет собой 128-битное число. Важно понимать: в самой структуре этого идентификатора не зашифрована информация о типе объекта. Ссылка в 1С (например, СправочникСсылка.Номенклатура) — это комбинация типа данных и самого GUID. Если мы знаем тип, мы легко получаем ссылку методом Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(УИДСтрокой)). Но если тип неизвестен, платформа не «знает», в какой таблице базы данных искать запись с этим идентификатором.
Самый эффективный способ решить проблему — не допускать потери типа на этапе выгрузки данных. Разберем, как передать объект целиком, чтобы на приемной стороне тип определился автоматически.
Использование ЗначениеВСтрокуВнутр()
Один из старейших способов — использование внутреннего формата 1С. Метод ЗначениеВСтрокуВнутр() преобразует ссылку в строку, содержащую и идентификатор типа, и сам GUID.
// На стороне выгрузки:
СтрокаДляФайла = ЗначениеВСтрокуВнутр(СсылкаНаОбъект);
// На стороне загрузки:
Ссылка = ЗначениеИзСтрокиВнутр(СтрокаИзФайла);
Важный нюанс: Несмотря на удобство, этот метод считается устаревшим и не рекомендуется для обмена между разными конфигурациями, так как внутренние идентификаторы типов (Metadata ID) в разных базах могут отличаться.
Использование XML и XDTO (Рекомендуемый способ)
Для надежной передачи данных лучше использовать механизмы XML-сериализации. Проанализируем пример функций, которые позволяют сохранить объект вместе с его типом в формате, понятном любой базе 1С:
Функция СериализоватьСсылкуВXML(Ссылка)
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Ссылка);
Возврат ЗаписьXML.Закрыть();
КонецФункции
Функция ДесериализоватьСсылкуИзXML(СтрокаXML)
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
Попытка
Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
Исключение
Возврат Неопределено;
КонецПопытки;
КонецФункции
Этот метод универсален: СериализаторXDTO автоматически добавит описание типа (например, CatalogRef.Номенклатура) в XML-структуру.
Если файл уже сформирован и в нем есть только GUID, нам придется «примерить» его ко всем возможным типам объектов в базе. Разберем алгоритм поиска. Нам нужно обойти коллекции справочников и документов, создавая ссылку для каждого типа и проверяя ее наличие в базе.
Проанализируем пример кода для поиска по всем справочникам:
Функция НайтиСсылкуПоGUIDВоВсехСправочниках(СтрокаGUID)
УИД = Новый УникальныйИдентификатор(СтрокаGUID);
Для Каждого МетаданныеСправочника Из Метаданные.Справочники Цикл
// Создаем ссылку для конкретного типа
Менеджер = Справочники[МетаданныеСправочника.Имя];
Ссылка = Менеджер.ПолучитьСсылку(УИД);
// Важно: ПолучитьСсылку() всегда возвращает ссылку,
// даже если объекта нет. Нужно проверить его наличие в БД.
Если НЕ Ссылка.ПолучитьОбъект() = Неопределено Тогда
Возврат Ссылка;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Особенности этого метода:
ПолучитьОбъект() инициирует тяжелое обращение к базе данных. Если справочников сотни, а GUID-ов в файле тысячи, поиск будет крайне медленным.ПолучитьОбъект() лучше использовать запрос к каждой таблице. Это значительно быстрее.Чтобы ускорить процесс, мы можем составить список всех возможных типов и выполнить поиск через временные таблицы или последовательные запросы. Выясним, как это сделать эффективнее. Вместо перебора всех метаданных «в лоб», мы можем ограничить поиск только теми типами, которые могут быть указаны в конкретном поле (например, типы, входящие в состав типа «Любая ссылка»).
Пример оптимизированной проверки через запрос:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);
Если НЕ Запрос.Выполнить().Пустой() Тогда
// Объект найден!
КонецЕсли;
Если база данных работает на SQL Server или PostgreSQL, и объем данных огромен, можно выполнить поиск средствами SQL. В таблицах 1С идентификатор хранится в поле _IDRRef в бинарном формате.
Рассмотрим порядок действий:
ПолучитьСтруктуруХраненияБазыДанных(), чтобы получить список имен всех SQL-таблиц, соответствующих справочникам и документам.UNION ALL или скриптом на стороне SQL.Этот способ является самым быстрым, но требует осторожности и понимания внутренней структуры хранения данных 1С.
Подводя итог, можно сказать, что ситуация «GUID без типа» является аварийной и ее стоит избегать на этапе проектирования системы. Рассмотрим ключевые правила:
ЗаписатьJSON с сохранением информации о типах).Метаданные.НайтиПоТипу() или XMLТипЗнч() может помочь вам восстановить строковое имя типа, если вы используете стандартные механизмы обмена платформы.Важно: Всегда проверяйте найденную ссылку на «пустоту» и наличие в базе, так как платформа 1С позволяет создать объект ссылки в оперативной памяти для любого GUID, даже если в базе данных такой записи никогда не существовало.