Как правильно передавать ссылки объектов через COM-соединение в 1С:Предприятие

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

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

Причина возникновения проблемы «непрозрачных» объектов

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

Решение 1: Получение строкового представления GUID через метод String

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


// Устанавливаем соединение с удаленной базой
COMСоединение = Новый COMОбъект("V83.COMConnector");
БазаИсточник = COMСоединение.Connect(СтрокаПодключения);

// Выполняем запрос на стороне удаленной базы
ЗапросCOM = БазаИсточник.NewObject("Запрос");
ЗапросCOM.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ Код = '00001'";
Результат = ЗапросCOM.Выполнить().Выбрать();

Если Результат.Следующий() Тогда
    // Используем метод String самого COM-соединения для получения GUID в виде строки
    СтрокаGUID = БазаИсточник.String(Результат.Ссылка.УникальныйИдентификатор());
    
    // Теперь в нашей текущей базе восстанавливаем ссылку по строковому GUID
    ЛокальныйGUID = Новый УникальныйИдентификатор(СтрокаGUID);
    ЛокальнаяСсылка = Справочники.Номенклатура.ПолучитьСсылку(ЛокальныйGUID);
    
    Если Не ЛокальнаяСсылка.Пустая() Тогда
        Сообщить("Объект успешно найден: " + ЛокальнаяСсылка);
    КонецЕсли;
КонецЕсли;

Важно отметить: мы вызываем метод String() именно у объекта БазаИсточник (COM-соединения). Это заставляет удаленную базу выполнить преобразование объекта в строку на своей стороне и вернуть нам уже готовый примитивный тип String, который 1С понимает без проблем.

Решение 2: Использование функции XMLСтрока

Разберем еще более надежный и быстрый метод — использование механизма XML-сериализации. Функция XMLString (или XMLСтрока в русской нотации) возвращает идентификатор ссылки в стандартном формате, который гарантированно одинаков для всех версий платформы. Это позволяет избежать проблем с внутренними форматами представления данных. Посмотрим на реализацию:


// На стороне базы-приемника получаем XML-представление ссылки из COM
СтрокаУИД = БазаИсточник.XMLString(СсылкаИзCOM);

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

Метод XMLString хорош тем, что он работает очень быстро и возвращает чистый GUID без лишних символов, что делает его идеальным для задач синхронизации в РИБ — упростить этот процесс поможет универсальный перенос данных между конфигурациями 1С через COM и HTTP.

Решение 3: Оптимизация передачи больших наборов данных

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

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


// На стороне удаленной базы создаем структуру для передачи
ДанныеДляПередачи = БазаИсточник.NewObject("Массив");

ЗапросCOM = БазаИсточник.NewObject("Запрос");
ЗапросCOM.Текст = "ВЫБРАТЬ Ссылка, Код, Наименование ИЗ Справочник.ФизическиеЛица";
Выборка = ЗапросCOM.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    СтруктураОбъекта = БазаИсточник.NewObject("Структура");
    СтруктураОбъекта.Вставить("GUID", БазаИсточник.XMLString(Выборка.Ссылка));
    СтруктураОбъекта.Вставить("Наименование", Выборка.Наименование);
    ДанныеДляПередачи.Добавить(СтруктураОбъекта);
КонецЦикла;

// Возвращаем весь массив целиком. На стороне приемника это будет один COM-объект,
// содержащий коллекцию структур с примитивными данными.

Хотя массив и структуры останутся COM-объектами, обращение к свойствам структур с примитивными типами внутри будет происходить значительно быстрее, чем работа с полноценными ссылками 1С через COM.

Разбор распространенных ошибок при работе с COM

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

  1. Контекст выполнения: Всегда создавайте объекты Запрос, Новый УникальныйИдентификатор и другие именно через менеджер COM-соединения (например, БазаИсточник.NewObject("Запрос")).
  2. Английский синтаксис: При работе через COM-соединение рекомендуется использовать англоязычные имена методов (NewObject, Execute, Select, Next), так как это повышает стабильность работы компоненты comcntr.dll.
  3. Освобождение памяти: После завершения работы обязательно обнуляйте переменные, содержащие COM-объекты (БазаИсточник = Неопределено), чтобы избежать утечек памяти на сервере.

Использование внутренних строк (ЗначениеВСтрокуВнутр)

Существует еще один метод — ЗначениеВСтрокуВнутр(). Он возвращает полную информацию об объекте в специальном формате 1С. Рассмотрим его использование:


ВнутренняяСтрока = БазаИсточник.ValueToStringInternal(СсылкаИзCOM);
// В основной базе
ЛокальнаяСсылка = ЗначениеИзСтрокиВнутр(ВнутренняяСтрока);

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

Заключение и рекомендации

Мы проанализировали основные способы работы со ссылками через COM-соединение в среде 1С. Подведем итоги: для РИБ-систем наиболее надежным и быстрым способом является передача УникальныйИдентификатор через метод XMLString. Если же вы работаете в современных конфигурациях на платформе 8.3, рассмотрите возможность замены COM-соединения на HTTP-сервисы. Они работают через JSON, что полностью исключает проблемы с типами данных и обеспечивает гораздо более высокую скорость и стабильность обмена данными.

← На главную