Как исправить ошибку «Отсутствует отображение для типа 'COMОбъект'» при подключении к другой базе 1С?

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

При настройке интеграции между различными конфигурациями «1С:Предприятие» разработчики часто сталкиваются с необходимостью организовать прямое подключение к базе-источнику для выборки и загрузки данных. Типичный сценарий — подключение из современной базы на управляемом приложении (например, 1С:ERP, 1С:Комплексная автоматизация или 1С:Управление торговлей) к устаревшей базе на обычных формах, такой как «1С:Управление производственным предприятием» (УПП) редакции 1.3.

Обе базы могут работать под управлением СУБД MS SQL Server. В процессе реализации такого подключения через механизм COMConnector часто возникает критическая ошибка передачи данных между клиентом и сервером. В этой статье мы подробно разберем причину возникновения данной проблемы и рассмотрим надежные способы ее устранения.

Выясняем причину ошибки XDTO-конвертации

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


Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа.
по причине:
Ошибка преобразования данных XDTO:
Запись значения свойства 'ret':
    форма: Элемент
    имя: {http://v8.1c.ru/8.2/managed-application/modules}ret по причине:
Ошибка отображения типов:
Отсутствует отображение для типа 'COMОбъект'

Давайте разберем, почему это происходит. В управляемом приложении 1С действует жесткое разделение контекстов выполнения кода на клиентский (&НаКлиенте) и серверный (&НаСервере).

Когда мы вызываем экспортную функцию получения COM-объекта, выполняющуюся на сервере (или в серверном общем модуле), и пытаемся вернуть результат ее работы обратно на клиент, платформа инициирует процесс сериализации данных. Передача любых данных между сервером «1С» и клиентским местом (будь то тонкий клиент или веб-клиент) осуществляется через XML-подобный формат XDTO.

Главное правило архитектуры 1С: Объект типа COMОбъект (как и Запрос, ВыборкаИзРезультатаЗапроса, ГрафическаяСхема и некоторые другие внутренние типы платформы) не является сериализуемым. Платформа физически не может преобразовать COM-соединение в XML-пакет для передачи по сети. Именно поэтому возникает ошибка отображения типов XDTO.

Решение №1: Перенос всей логики работы с COM на сторону сервера (Рекомендуемое)

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

Рассмотрим по шагам, как переписать логику подключения и выборки документа «Поступление товаров и услуг» из базы УПП 1.3.

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

Посмотрим на пример реализации серверной функции:


&НаСервере
Функция ПолучитьДанныеДокументаИзУПП(НомерДокумента, ДатаДокумента)
    
    // 1. Формируем строку подключения к SQL-базе источника
    СтрокаПодключения = "srvr='ИмяСервераБД'; ref='ИмяБазыУПП'; usr='Логин'; pwd='Пароль';";
    
    // 2. Инициализируем COM-соединение локально на сервере
    ИмяComОбъекта = "V83.COMConnector"; // Или V82.COMConnector в зависимости от платформы источника
    
    Попытка
        COMConnector = Новый COMОбъект(ИмяComОбъекта);
        СоединениеИсточника = COMConnector.Connect(СтрокаПодключения);
    Исключение
        ВызватьИсключение "Не удалось установить подключение к УПП: " + ОписаниеОшибки();
    КонецПопытки;
    
    // 3. Создаем структуру для возврата данных
    ДанныеДокумента = Новый Структура;
    ДанныеДокумента.Вставить("ДокументНайден", Ложь);
    ДанныеДокумента.Вставить("Реквизиты", Новый Структура);
    ДанныеДокумента.Вставить("ТабличнаяЧастьТовары", Новый Массив);
    
    // 4. Ищем документ в базе источника средствами COM
    // Используем менеджер запросов внешней базы для быстрого поиска
    ЗапросИсточника = СоединениеИсточника.NewObject("Запрос");
    ЗапросИсточника.Текст = 
        "ВЫБРАТЬ
        |   Ссылка,
        |   Контрагент.Наименование КАК КонтрагентНаименование,
        |   ДоговорКонтрагента.Наименование КАК ДоговорНаименование,
        |   Организация.Наименование КАК ОрганизацияНаименование
        |ИЗ
        |   Документ.ПоступлениеТоваровУслуг КАК Поступление
        |ГДЕ
        |   Поступление.Номер = &Номер
        |   И Поступление.Дата = &Дата";
        
    ЗапросИсточника.УстановитьПараметр("Номер", НомерДокумента);
    ЗапросИсточника.УстановитьПараметр("Дата", ДатаДокумента);
    
    РезультатЗапроса = ЗапросИсточника.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        
        ДанныеДокумента.ДокументНайден = Истина;
        
        // Заполняем структуру реквизитов (передаем только простые типы: строки, числа, даты)
        СтруктураРеквизитов = ДанныеДокумента.Реквизиты;
        СтруктураРеквизитов.Вставить("КонтрагентНаименование", Выборка.КонтрагентНаименование);
        СтруктураРеквизитов.Вставить("ДоговорНаименование", Выборка.ДоговорНаименование);
        СтруктураРеквизитов.Вставить("ОрганизацияНаименование", Выборка.ОрганизацияНаименование);
        
        // Получаем табличную часть "Товары" через COM-объект ссылки
        СсылкаНаДокумент = Выборка.Ссылка;
        Для Каждого СтрокаТовары Из СсылкаНаДокумент.Товары Цикл
            СтрокаТЧ = Новый Структура;
            СтрокаТЧ.Вставить("НоменклатураНаименование", СтрокаТовары.Номенклатура.Наименование);
            СтрокаТЧ.Вставить("Количество", СтрокаТовары.Количество);
            СтрокаТЧ.Вставить("Цена", СтрокаТовары.Цена);
            СтрокаТЧ.Вставить("Сумма", СтрокаТовары.Сумма);
            
            ДанныеДокумента.ТабличнаяЧастьТовары.Добавить(СтрокаТЧ);
        КонецЦикла;
        
    КонецЕсли;
    
    // Освобождаем COM-объекты явным образом
    СоединениеИсточника = Неопределено;
    COMConnector = Неопределено;
    
    Возврат ДанныеДокумента;

КонецФункции

При таком подходе на клиент возвращается обычная сериализуемая структура ДанныеДокумента, содержащая массивы простых структур. Это полностью исключает возникновение ошибок XDTO-конвертации и обеспечивает быструю передачу данных по сети.

Решение №2: Инициализация COM-соединения на клиенте

Если архитектура вашего решения предполагает интерактивный выбор документов пользователем непосредственно из формы (например, динамическое открытие списков внешней базы прямо в интерфейсе приемника), мы можем инициализировать COM-объект непосредственно в контексте &НаКлиенте.

Для реализации этого метода необходимо соблюдение нескольких условий:

  1. Пользователь работает через Тонкий клиент или Толстый клиент под управлением операционной системы семейства Microsoft Windows.
  2. На локальном компьютере пользователя зарегистрирована библиотека comcntr.dll соответствующей версии платформы «1С».

Проанализируем пример клиентского подключения:


&НаКлиенте
Процедура ПодключитьсяКИсточникуНаКлиенте()
    
    СтрокаПодключения = "srvr='ИмяСервераБД'; ref='ИмяБазыУПП'; usr='Логин'; pwd='Пароль';";
    
    Попытка
        // Создаем объект непосредственно в памяти клиентского процесса
        COMConnector = Новый COMОбъект("V83.COMConnector");
        COMConnection = COMConnector.Connect(СтрокаПодключения);
        ПоказатьПредупреждение(, "Успешно подключено на клиенте!");
    Исключение
        ПоказатьПредупреждение(, "Ошибка подключения на клиенте: " + ОписаниеОшибки());
    КонецПопытки;
    
    // Здесь мы можем использовать COMConnection для интерактивной работы в рамках этой процедуры
    
КонецПроцедуры

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

Почему COM-соединение предпочтительнее, чем прямое подключение через ADO?

В ходе обсуждений на форумах часто звучат предложения отказаться от COM-соединения в пользу прямого чтения таблиц базы данных SQL Server через механизм ADO (ActiveX Data Objects). Давайте выясним, почему для бизнес-задач (таких как загрузка документов 1С) это является крайне неэффективным решением:

Использование COMConnector позволяет абстрагироваться от низкоуровневой структуры SQL-таблиц и работать с привычными объектами метаданных 1С на стандартном встроенном языке.

Технические нюансы и подводные камни при настройке COM

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

  1. Разрядность сервера приложений 1С:

    Если сервер «1С:Предприятия» базы-приемника является 64-разрядным (64-bit), то для выполнения кода на сервере должна быть зарегистрирована 64-битная версия библиотеки comcntr.dll. Если вы получаете ошибку «Класс не зарегистрирован», выполните регистрацию библиотеки вручную через командную строку от имени администратора:

    regsvr32 "C:\Program Files\1cv8\[ВерсияПлатформы]\bin\comcntr.dll"
  2. Настройка службы компонентов COM+:

    В некоторых случаях (особенно при работе под управлением Windows Server) учетная запись, от имени которой запущен сервер приложений «1С» (обычно это usr1cv8), не имеет достаточных прав для создания DCOM-объектов. Решением является создание выделенного приложения COM+ в «Службах компонентов» Windows, куда добавляется библиотека comcntr.dll, и настройка запуска этого приложения от имени администратора системы.

  3. Лицензирование:

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

Современная альтернатива: Переход на HTTP-сервисы

Если обе базы данных находятся в активной разработке, мы рекомендуем рассмотреть более современную и кроссплатформенную альтернативу COM-соединениям — использование HTTP-сервисов.

Вы можете опубликовать в базе УПП 1.3 простейший HTTP-сервис, который будет принимать запросы с параметрами (номер и дата документа) и возвращать структурированные данные в формате JSON. База-приемник сможет отправлять стандартные HTTP-запросы с помощью встроенного класса платформы HTTPСоединение.

Этот подход обладает неоспоримыми преимуществами:

← На главную