Как перенести элементы справочника с сохранением Уникального Идентификатора (UUID) через COM-соединение?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При обмене данными между двумя базами 1С часто возникает задача сохранить идентичность объектов. Лучший способ сделать это — перенести объект с тем же Уникальным Идентификатором (UUID/GUID). Однако при реализации этой задачи через COM-соединение программисты часто сталкиваются с неочевидными ошибками. В этой статье мы разберем, как правильно передавать UUID, обходить ограничения мутабельности и работать с метаданными объектов во внешней базе.

Проблема передачи UUID через COM-соединение

Типичная ошибка новичка заключается в попытке напрямую передать объект УникальныйИдентификатор из внешней базы в локальный конструктор. Рассмотрим ситуацию: мы получаем ссылку на контрагента из внешней базы и хотим создать такую же в текущей. Если написать код напрямую, как в примере ниже, платформа выдаст ошибку "Неверный параметр":


УидВоВнешнейБазе = КонтрСоб.Ссылка.УникальныйИдентификатор();
// Ошибка произойдет здесь:
УидВЭтойБазе = Новый УникальныйИдентификатор(Строка(УидВоВнешнейБазе));

Причина заключается в том, что COM-объект, возвращаемый внешней базой, не является стандартной строкой или типом, который локальный конструктор УникальныйИдентификатор может распознать корректно. Выясним причину: внешняя база передает COM-объект, и прямое преобразование Строка() может отработать не так, как ожидается в контексте разных сессий.

Решение через XML-сериализацию

Для гарантированного получения строкового представления идентификатора следует использовать механизм XML. Однако здесь есть важный нюанс. Если вызвать локальную функцию XMLСтрока() и передать ей идентификатор из внешней базы, мы получим ошибку "Ошибка преобразования данных XML".

Правильное решение: вызывать метод XMLСтрока непосредственно через объект подключения к внешней базе. Проанализируем правильную конструкцию:


// БазаОткрыта - это наше COM-соединение (V83.COMConnector)
УидСтрокой = БазаОткрыта.XMLСтрока(КонтрСоб.Ссылка.УникальныйИдентификатор());
УидВЭтойБазе = Новый УникальныйИдентификатор(УидСтрокой);

НовыйОбъект = Справочники.Контрагенты.СоздатьЭлемент();
НовыйОбъект.УстановитьСсылкуНового(Справочники.Контрагенты.ПолучитьСсылку(УидВЭтойБазе));

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

Борьба с мутабельными значениями

При работе с COM-соединением часто возникает ошибка: "Проверка мутабельных значений на заполненность не поддерживается". Разберем, почему это происходит. Мутабельные значения — это сложные объекты (таблицы значений, структуры, ссылки), которые могут изменяться. Передавать их "через границу" COM-соединения в локальные функции 1С нельзя.

Рассмотрим пример кода, вызывающий ошибку:


Если ЗначениеЗаполнено(Источник[НаимРеквизита]) Тогда 
    // Ошибка: Источник[НаимРеквизита] — это мутабельное значение из внешней базы
КонецЕсли;

Чтобы избежать этой проблемы, мы должны выполнять проверку на стороне той базы, которой принадлежит объект. Используем объект соединения:


Если БазаОткрыта.ЗначениеЗаполнено(Источник[НаимРеквизита]) Тогда 
    // Так проверка отработает корректно
КонецЕсли;

Это золотое правило работы с COM: все операции над объектами внешней базы (проверка заполненности, поиск, получение метаданных) должны выполняться через методы этой самой базы.

Работа с метаданными: как определить владельца справочника

При универсальном переносе данных нам часто нужно знать структуру объекта "на лету". Например, есть ли у справочника владелец? Если мы попытаемся обратиться к метаданным напрямую, мы снова можем столкнуться с трудностями интерпретации типов.

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


// СправочникОбъект получен из внешней базы
КоличествоВладельцев = СправочникОбъект.Метаданные().Владельцы.Количество();

Если КоличествоВладельцев > 0 Тогда
    // Логика обработки владельца
КонецЕсли;

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

Важные рекомендации по методу УстановитьСсылкуНового()

Рассмотрим несколько критических моментов, которые помогут избежать ошибок при записи объектов в SQL-базу:

  1. Только для новых объектов: Метод УстановитьСсылкуНового() работает исключительно до первого вызова Записать(). Если объект уже существует в базе, сменить его UUID программно невозможно.
  2. Проверка на уникальность: Перед установкой ссылки обязательно проверьте, не занят ли этот идентификатор уже существующим объектом. В SQL-базах попытка записи объекта с дублирующим UUID приведет к критической ошибке СУБД.
  3. Типизация: При переносе данных между разными конфигурациями убедитесь, что длина наименования и типы реквизитов совпадают. SQL-версия 1С гораздо строже относится к переполнению строк или несоответствию типов, чем файловая.

Подводя итог, можно сказать, что перенос данных с сохранением UUID — это мощный инструмент синхронизации, но он требует аккуратного обращения с контекстами выполнения. Всегда приводите сложные типы к примитивным (строкам или числам) при передаче через COM и используйте методы внешней базы для анализа ее же объектов.

← На главную