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

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

Работа с внешними источниками данных через COM-соединение (V83.COMConnector) является стандартной задачей при интеграции различных информационных баз 1С. Однако начинающие разработчики часто сталкиваются с трудностями при попытке получить привычные данные, такие как текстовое представление ссылки или имя типа документа, поскольку объекты на "той стороне" соединения ведут себя иначе, чем в контексте текущей базы. В данной статье мы подробно разберем, как корректно извлекать информацию об объектах через COM, минимизируя ошибки и потерю производительности.

Получение текстового представления объекта

Когда нам нужно получить строку вида "Реализация №5466 от 01.01.2019", обычное обращение к объекту или попытка приведения типа на стороне вызывающей базы не сработает. Это связано с тем, что COM-объект ссылки не преобразуется автоматически в строку в контексте вашей текущей сессии. Чтобы получить человекочитаемое представление, мы должны использовать методы глобального контекста той базы, к которой подключились.

Проанализируем наиболее эффективный способ. Для этого обратимся к методу String() самого объекта COM-соединения. Рассмотрим пример кода:


// Предположим, МоёКомСоединение уже установлено
// МояКомСсылка — это объект ссылки, полученный из внешней базы
ПредставлениеОбъекта = МоёКомСоединение.String(МояКомСсылка);
Сообщить(ПредставлениеОбъекта); // Выведет: Реализация товаров и услуг...

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

Работа с уникальными идентификаторами (UUID)

Для однозначной идентификации объекта в разных базах (например, для синхронизации) нам требуется получить его УникальныйИдентификатор. Напрямую обратиться к свойству УникальныйИдентификатор() можно, но результат будет передан как специфический COM-объект. Чтобы работать с ним как со строкой, следует выполнить преобразование на удаленной стороне.

Разберем, как это сделать правильно:


// Получаем UUID как COM-объект и сразу преобразуем его в строку
СтрокаGUID = МоёКомСоединение.String(МояКомСсылка.UUID());

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

  1. Получаем строковое значение GUID из COM-базы.
  2. Создаем новый объект УникальныйИдентификатор в локальной базе.
  3. Используем менеджер документа для получения ссылки по идентификатору.

// Пример реконструкции ссылки
GUIDСтрокой = МоёКомСоединение.String(МояКомСсылка.UUID());
НовыйУИ = Новый УникальныйИдентификатор(GUIDСтрокой);
ЛокальнаяСсылка = Документы.РеализацияТоваровУслуг.ПолучитьСсылку(НовыйУИ);

Определение типа объекта и метаданных

Часто при обмене данными необходимо программно определить, к какому типу относится полученная ссылка (например, это "РеализацияТоваровУслуг" или "ПоступлениеТоваровУслуг"). Попытка вызвать ТипЗнч() в локальном коде вернет общий тип COMОбъект. Чтобы узнать истинный тип, мы должны обратиться к метаданным удаленной базы.

Рассмотрим два способа получения имени типа:

Способ 1. Через метод Metadata() ссылки:

Каждая ссылка в COM-соединении имеет доступ к своим метаданным. Мы можем напрямую запросить имя объекта:


ИмяТипа = МояКомСсылка.Metadata().Name;
// Вернет, например, "РеализацияТоваровУслуг"

Способ 2. Через глобальный метод TypeValue:

Если нам нужно сравнить тип объекта с конкретным типом, лучше использовать метод TypeValue, который доступен через объект соединения:


ТипОбъекта = МоёКомСоединение.TypeValue(МояКомСсылка);
Если ТипОбъекта = МоёКомСоединение.Type("DocumentRef.РеализацияТоваровУслуг") Тогда
    // Выполняем логику для конкретного документа
КонецЕсли;

Использование XML-сериализации для передачи данных

В некоторых случаях удобно передавать данные через XML-строку. Метод XMLСтрока() позволяет быстро получить строковое представление ссылки, которое включает в себя UUID. Однако, как отмечают разработчики, при прямом вызове XMLСтрока(МояКомСсылка) может возникнуть ошибка преобразования. Выясним причину: локальная база не знает, как сериализовать чужой COM-объект.

Решение заключается в вызове этого метода именно на стороне COM-соединения:

ТекСтрокаXML = МоёКомСоединение.XMLСтрока(МояКомСсылка);

Этот метод возвращает внутреннее представление ссылки, которое часто используется в механизмах обмена данными. Но стоит помнить, что для простого отображения пользователю метод String() подходит гораздо лучше.

Оптимизация производительности с помощью Eval и Execute

Одной из главных проблем COM-соединения является низкая скорость работы при большом количестве обращений ("пинг" между процессами). Если нам нужно получить данные для тысячи документов, обращение к каждому свойству (.Number, .Date, .Metadata().Name) по отдельности создаст огромную нагрузку.

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


// Формируем запрос на получение данных одной транзакцией
КодДляВыполнения = "
|Стр = Новый Структура;
|Стр.Вставить(""Представление"", String(Объект));
|Стр.Вставить(""ИмяТипа"", Объект.Metadata().Name);
|Стр.Вставить(""GUID"", String(Объект.UUID()));
|Возврат Стр;";

// Передаем объект в контекст выполнения (если это возможно) 
// или используем поиск внутри Eval
Данные = МоёКомСоединение.Eval(СтрЗаменить(КодДляВыполнения, "Объект", "Документы.РеализацияТоваровУслуг.НайтиПоНомеру(""5466"")"));

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

Проверка на "битые" и пустые ссылки

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

Рассмотрим правильный алгоритм проверки:

  1. Проверить на заполненность методом ValueIsFilled.
  2. Использовать метод IsEmpty() (Пустая()) самой ссылки.
  3. Для критически важных участков использовать конструкцию Попытка...Исключение.

Если МоёКомСоединение.ValueIsFilled(МояКомСсылка) Тогда
    Попытка
        ИмяТипа = МояКомСсылка.Metadata().Name;
    Исключение
        Сообщить("Объект не найден в базе-источнике (битая ссылка)");
    КонецПопытки;
КонецЕсли;

Особенности настройки COM на 64-битных серверах

Иногда даже при правильном коде попытка получить метаданные через COM завершается ошибкой "Класс не зарегистрирован" или ошибками доступа к памяти. Это часто происходит на 64-битных серверах 1С, так как библиотека comcntr.dll по умолчанию может конфликтовать с разрядностью процессов.

Для решения этой проблемы мы рекомендуем:

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

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

← На главную