Работа с внешними базами данных через COM-соединение (COMConnector) — классическая задача при интеграции систем на платформе 1С:Предприятие. Несмотря на развитие технологий Web-сервисов и HTTP-запросов, COM остается востребованным инструментом благодаря возможности прямого обращения к объектам метаданных другой базы. Однако при написании кода программисты часто сталкиваются с неочевидными нюансами передачи типов данных и обращения к методам. В этой статье мы подробно разберем, как правильно реализовать запрос через COM-соединение, избежать ошибок типизации и оптимизировать производительность.
Рассмотрим ситуацию, когда необходимо подключиться к внешней базе, найти там сотрудника и заполнить реквизиты документа в текущей базе. Типичная ошибка начинающих разработчиков заключается в попытке передать локальную ссылку (например, СправочникСсылка.ФизическиеЛица) напрямую в параметр запроса COM-объекта. Проанализируем, почему это не работает: ссылка в текущей базе — это уникальный идентификатор (GUID), который не имеет никакого смысла в контексте другой базы данных, даже если это идентичные конфигурации. Каждая база живет в своем адресном пространстве.
Разберем типичный ошибочный код:
// ОШИБОЧНЫЙ ПОДХОД
ФизЛицо = Справочники.ФизическиеЛица.НайтиПоНаименованию("Иванов Иван Иванович");
ЗапросВ.УстановитьПараметр("ФизическоеЛицо", ФизЛицо); // Передается локальная ссылка!
В данном случае внешняя база получит объект, который она не сможет сопоставить со своими данными. Правильный путь — передавать в качестве параметров примитивные типы (строки, числа, даты) или искать ссылку уже внутри COM-соединения.
Выясним причину, по которой поиск часто возвращает пустой результат. Чтобы запрос во внешней базе отработал корректно, мы должны либо передать строку (например, ИНН или Наименование) и искать по ней внутри текста запроса, либо сначала найти объект в COM-базе и уже его передать в параметр. Рассмотрим второй вариант подробнее.
Проанализируем пример кода, в котором поиск ссылки осуществляется средствами внешней базы:
// Правильная подготовка параметра
// Ищем ссылку именно через объект COM-соединения
ИмяСотрудника = "Иванов Иван Иванович";
СотрудникВнешний = КомСоединение.Справочники.ФизическиеЛица.НайтиПоНаименованию(ИмяСотрудника);
// Теперь передаем полученный COM-объект (ссылку внешней базы) в параметр запроса
ЗапросВ = КомСоединение.NewObject("Запрос");
ЗапросВ.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Сотрудники ГДЕ ФизическоеЛицо = &ФизическоеЛицо";
ЗапросВ.УстановитьПараметр("ФизическоеЛицо", СотрудникВнешний);
В этом примере СотрудникВнешний является прокси-объектом, который понятен внешней базе. Это критически важный момент для успешного выполнения запроса.
Часто при попытке выгрузить результат запроса возникает ошибка: "Метод объекта не обнаружен (Выгрузить)". Посмотрим на причину: метод Выгрузить() принадлежит объекту РезультатЗапроса, а не самому объекту Запрос. При работе через COM-соединение цепочки вызовов должны быть очень строгими.
Рассмотрим по шагам правильный алгоритм получения данных:
Выполнить() у объекта запроса.РезультатЗапроса (как COM-объект).Выбрать() для обхода или Выгрузить() для получения таблицы.Посмотрим на пример кода, который корректно обрабатывает выборку:
com_Результат = ЗапросВ.Выполнить(); // Получаем результат запроса
com_Выборка = com_Результат.Выбрать(); // Создаем выборку
Пока com_Выборка.Следующий() Цикл
// Работаем с данными. Помните: com_Выборка.Сотрудник — это тоже COM-объект!
Сообщить("Найден сотрудник: " + Строка(com_Выборка.Сотрудник));
КонецЦикла;
Если нам необходимо передать всю таблицу значений из внешней базы в локальную, мы сталкиваемся с тем, что типы колонок таблицы во внешней базе — это COM-объекты. Прямое присваивание ТЗ_Локальная = com_ТЗ_Внешняя не превратит внешние ссылки в локальные.
Для передачи данных часто используют сериализацию. Разберем метод с использованием ЗначениеВСтрокуВнутр (хотя для современных систем рекомендуется JSON):
// На стороне внешней базы выгружаем результат в ТЗ
com_ТЗ = com_Результат.Выгрузить();
// Преобразуем ТЗ в строку внутреннего формата на стороне ВНЕШНЕЙ базы
стр_ТЗ = КомСоединение.ЗначениеВСтрокуВнутр(com_ТЗ);
// В локальной базе восстанавливаем ТЗ из строки
ТЗ_Локальная = ЗначениеИзСтрокиВнутр(стр_ТЗ);
Важное замечание: Метод ЗначениеВСтрокуВнутр сработает корректно только в том случае, если структуры метаданных в обеих базах идентичны (например, при обмене между узлами РИБ). Если конфигурации разные, ссылки все равно останутся "битыми". В таких случаях лучше выгружать данные в структуру или массив простых типов (строк и чисел).
Проанализируем производительность. Каждый раз, когда мы пишем com_Выборка.Следующий() или обращаемся к свойству com_Выборка.Наименование, программа совершает сетевой вызов (RPC) к другому процессу или серверу. Если в выборке 1000 строк и в каждой 10 реквизитов, вы совершите 10 000 сетевых обращений. Это крайне медленно.
Рекомендация по оптимизации:
Вместо выполнения запроса в локальном коде через КомСоединение.NewObject("Запрос"), лучше создать в подключаемой базе специальный экспортный общий модуль. В этом модуле напишите функцию, которая выполняет всю работу (запрос, обработку, формирование структуры) и возвращает один объект (например, строку JSON или массив структур). Тогда вы совершите всего ОДИН вызов через COM-соединение, что ускорит работу в десятки раз.
// Вместо этого:
Запрос = КомСоединение.NewObject("Запрос"); // Вызов 1
Запрос.Текст = "..."; // Вызов 2
Результат = Запрос.Выполнить(); // Вызов 3
// ... и так далее ...
// Делайте так:
// В подключаемой базе создаем функцию ПолучитьДанныеСотрудников(Параметры)
// В локальной базе вызываем её одним махом:
Результат = КомСоединение.МодульИнтеграции.ПолучитьДанныеСотрудников(ПараметрыПоиска);
Не забывайте, что COM-соединение потребляет лицензию 1С и ресурсы сервера. После завершения работы обязательно очищайте переменную соединения:
КомСоединение = Неопределено;
Также всегда используйте конструкцию Попытка...Исключение при установке соединения и выполнении запросов. Это позволит корректно обработать ситуации, когда внешняя база недоступна или у пользователя недостаточно прав на выполнение запроса к конкретному справочнику.
Подводя итог, при работе с запросами через COM ключевыми факторами успеха являются: использование строковых идентификаторов для поиска объектов, понимание разницы между объектом запроса и результатом запроса, а также минимизация количества обращений к свойствам COM-объектов в циклах.