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

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

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

Анализ основной проблемы: почему запрос не возвращает данные

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

Разберем типичный ошибочный код:


// ОШИБОЧНЫЙ ПОДХОД
ФизЛицо = Справочники.ФизическиеЛица.НайтиПоНаименованию("Иванов Иван Иванович");
ЗапросВ.УстановитьПараметр("ФизическоеЛицо", ФизЛицо); // Передается локальная ссылка!

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

Шаг 1: Правильная передача параметров в COM-запрос

Выясним причину, по которой поиск часто возвращает пустой результат. Чтобы запрос во внешней базе отработал корректно, мы должны либо передать строку (например, ИНН или Наименование) и искать по ней внутри текста запроса, либо сначала найти объект в COM-базе и уже его передать в параметр. Рассмотрим второй вариант подробнее.

Проанализируем пример кода, в котором поиск ссылки осуществляется средствами внешней базы:


// Правильная подготовка параметра
// Ищем ссылку именно через объект COM-соединения
ИмяСотрудника = "Иванов Иван Иванович";
СотрудникВнешний = КомСоединение.Справочники.ФизическиеЛица.НайтиПоНаименованию(ИмяСотрудника);

// Теперь передаем полученный COM-объект (ссылку внешней базы) в параметр запроса
ЗапросВ = КомСоединение.NewObject("Запрос");
ЗапросВ.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Сотрудники ГДЕ ФизическоеЛицо = &ФизическоеЛицо";
ЗапросВ.УстановитьПараметр("ФизическоеЛицо", СотрудникВнешний);

В этом примере СотрудникВнешний является прокси-объектом, который понятен внешней базе. Это критически важный момент для успешного выполнения запроса.

Шаг 2: Выполнение запроса и обработка результата

Часто при попытке выгрузить результат запроса возникает ошибка: "Метод объекта не обнаружен (Выгрузить)". Посмотрим на причину: метод Выгрузить() принадлежит объекту РезультатЗапроса, а не самому объекту Запрос. При работе через COM-соединение цепочки вызовов должны быть очень строгими.

Рассмотрим по шагам правильный алгоритм получения данных:

  1. Вызываем метод Выполнить() у объекта запроса.
  2. Получаем объект РезультатЗапроса (как COM-объект).
  3. Вызываем Выбрать() для обхода или Выгрузить() для получения таблицы.

Посмотрим на пример кода, который корректно обрабатывает выборку:


com_Результат = ЗапросВ.Выполнить(); // Получаем результат запроса
com_Выборка = com_Результат.Выбрать(); // Создаем выборку

Пока com_Выборка.Следующий() Цикл
    // Работаем с данными. Помните: com_Выборка.Сотрудник — это тоже COM-объект!
    Сообщить("Найден сотрудник: " + Строка(com_Выборка.Сотрудник));
КонецЦикла;

Шаг 3: Передача Таблицы Значений через COM

Если нам необходимо передать всю таблицу значений из внешней базы в локальную, мы сталкиваемся с тем, что типы колонок таблицы во внешней базе — это COM-объекты. Прямое присваивание ТЗ_Локальная = com_ТЗ_Внешняя не превратит внешние ссылки в локальные.

Для передачи данных часто используют сериализацию. Разберем метод с использованием ЗначениеВСтрокуВнутр (хотя для современных систем рекомендуется JSON):


// На стороне внешней базы выгружаем результат в ТЗ
com_ТЗ = com_Результат.Выгрузить();

// Преобразуем ТЗ в строку внутреннего формата на стороне ВНЕШНЕЙ базы
стр_ТЗ = КомСоединение.ЗначениеВСтрокуВнутр(com_ТЗ);

// В локальной базе восстанавливаем ТЗ из строки
ТЗ_Локальная = ЗначениеИзСтрокиВнутр(стр_ТЗ);

Важное замечание: Метод ЗначениеВСтрокуВнутр сработает корректно только в том случае, если структуры метаданных в обеих базах идентичны (например, при обмене между узлами РИБ). Если конфигурации разные, ссылки все равно останутся "битыми". В таких случаях лучше выгружать данные в структуру или массив простых типов (строк и чисел).

Оптимизация: Почему ваш COM-запрос может тормозить?

Проанализируем производительность. Каждый раз, когда мы пишем com_Выборка.Следующий() или обращаемся к свойству com_Выборка.Наименование, программа совершает сетевой вызов (RPC) к другому процессу или серверу. Если в выборке 1000 строк и в каждой 10 реквизитов, вы совершите 10 000 сетевых обращений. Это крайне медленно.

Рекомендация по оптимизации:

Вместо выполнения запроса в локальном коде через КомСоединение.NewObject("Запрос"), лучше создать в подключаемой базе специальный экспортный общий модуль. В этом модуле напишите функцию, которая выполняет всю работу (запрос, обработку, формирование структуры) и возвращает один объект (например, строку JSON или массив структур). Тогда вы совершите всего ОДИН вызов через COM-соединение, что ускорит работу в десятки раз.


// Вместо этого:
Запрос = КомСоединение.NewObject("Запрос"); // Вызов 1
Запрос.Текст = "..."; // Вызов 2
Результат = Запрос.Выполнить(); // Вызов 3
// ... и так далее ...

// Делайте так:
// В подключаемой базе создаем функцию ПолучитьДанныеСотрудников(Параметры)
// В локальной базе вызываем её одним махом:
Результат = КомСоединение.МодульИнтеграции.ПолучитьДанныеСотрудников(ПараметрыПоиска);

Безопасность и очистка ресурсов

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

КомСоединение = Неопределено;

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

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

← На главную