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

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

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

Причина возникновения ошибки типизации

Разберем ситуацию: когда мы создаем COM-соединение, мы фактически работаем с двумя разными адресными пространствами. Локальный объект Массив, созданный в вашей текущей базе, "не знаком" удаленной базе. Несмотря на то, что типы называются одинаково, это объекты разных экземпляров платформы. Через границы COM-соединения без проблем проходят только примитивные типы данных: Число, Строка, Дата и Булево.

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

Способ 1. Создание объекта коллекции в удаленной базе

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


// Предположим, у нас есть локальная Таблица Значений ТЗPDM с колонкой "Код"
СЗКод_Локальный = ТЗPDM.ВыгрузитьКолонку("Код");

// Создаем объект СписокЗначений или Массив непосредственно в удаленной базе
СписокУдаленный = БазаУПП.NewObject("СписокЗначений");

// Теперь наполняем удаленный список данными. 
// Важно: добавляем только примитивные типы (в данном случае строки кодов)
Для Каждого Элемент Из СЗКод_Локальный Цикл
    СписокУдаленный.Добавить(Элемент);
КонецЦикла;

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

ЗапросУПП.УстановитьПараметр("СписокКодов", СписокУдаленный);
Результат = ЗапросУПП.Выполнить().Выгрузить();

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

Способ 2. Оптимизация передачи больших данных

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

Для ускорения работы мы рекомендуем использовать передачу данных одной строкой. Выясним, как это сделать:

  1. Сформируем в локальной базе строку, где все коды разделены специальным символом (например, запятой).
  2. Передадим эту строку как один параметр в удаленную базу.
  3. В самой удаленной базе вызовем функцию, которая разложит строку обратно в массив.

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

Способ 3. Передача ссылочных данных через GUID

Если нам нужно передать в параметр не коды (строки), а ссылки на объекты, ситуация усложняется. Ссылки одной базы недействительны в другой. Однако, если базы синхронизированы, мы можем использовать Уникальный Идентификатор (GUID). Рассмотрим алгоритм действий: для миграции данных между похожими конфигурациями с сопоставлением объектов по идентификаторам используется инструмент переноса данных с поиском по произвольным полям.

Во-первых, в локальной базе получим строковое представление GUID ссылки:

СтрокаGUID = Строка(СсылкаЛокальная.УникальныйИдентификатор());

Во-вторых, в удаленной базе найдем объект по этому идентификатору:


ИдентификаторУдаленный = БазаУПП.NewObject("УникальныйИдентификатор", СтрокаGUID);
СсылкаУдаленная = БазаУПП.Справочники.ЕдиницыИзмерения.ПолучитьСсылку(ИдентификаторУдаленный);

// Теперь эту ссылку можно добавить в массив, созданный через NewObject в удаленной базе
СписокУдаленный.Добавить(СсылкаУдаленная);

Нюансы производительности и ограничения

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

Итоговые рекомендации

Подводя итог, при работе с запросами через COM-соединение всегда придерживайтесь правила: параметры должны подготавливаться в целевой среде. Не пытайтесь "протолкнуть" сложные локальные объекты сквозь COM-интерфейс. Используйте NewObject для создания коллекций, передавайте GUID для ссылок и минимизируйте количество вызовов методов в циклах, отдавая предпочтение пакетной передаче данных в виде строк или XML/JSON.

← На главную