При интеграции двух баз 1С с помощью COMConnector разработчики часто сталкиваются с ситуацией, когда запрос, успешно работающий внутри основной базы, при вызове во внешней базе через COM-соединение выдает исключение «Неверные параметры».
Разберем причины возникновения этой проблемы и проанализируем способы ее решения на конкретных примерах.
Рассмотрим стандартный сценарий: из текущей базы выполняется подключение к внешней базе через COM-объект, создается объект Запрос и устанавливаются параметры отбора (например, список подразделений).
Ошибка «Неверные параметры» при выполнении метода Запрос.Выполнить() чаще всего возникает по нескольким причинам:
Подразделение.Наименование В (&Подразделение)), а в параметр передается список или массив ссылок на элементы справочника (тип СправочникСсылка или COM-объект), либо наоборот.СписокЗначений текущей базы во внешний запрос COM-соединения может вызывать ошибки приведения типов. Для внешнего запроса коллекция должна либо создаваться во внешнем соединении, либо передаваться в виде обычного локального массива примитивных типов (строк, чисел, дат).Запрос.Текст, платформе не с чем сопоставить передаваемые структуры данных.Если условие запроса построено по наименованию (...Подразделение.Наименование В (&Подразделение)), в параметр необходимо передавать массив строк примитивного типа. Платформа 1С автоматически и корректно передает примитивные типы через COM-границу.
Рассмотрим пример кода, в котором собирается массив наименований из формы и передается в запрос:
// 1. Создаем обычный локальный массив строк
МассивНаименований = Новый Массив;
Для Каждого Стр Из ПолеСпискаПодразделений Цикл
Если Стр.Пометка Тогда
// Добавляем строковое значение наименования
МассивНаименований.Добавить(Строка(Стр.Значение));
КонецЕсли;
КонецЦикла;
// 2. Создаем запрос во внешней базе через COM
ЗапросCOM = Connection1C.NewObject("Запрос");
// 3. Сначала обязательно задаем текст запроса
ЗапросCOM.Текст =
"ВЫБРАТЬ
| Подразделения.Ссылка КАК Подразделение,
| Подразделения.Наименование КАК Наименование
|ИЗ
| Справочник.ПодразделенияОрганизаций КАК Подразделения
|ГДЕ
| Подразделения.Наименование В (&Подразделение)";
// 4. Устанавливаем параметр (передаем массив строк)
ЗапросCOM.УстановитьПараметр("Подразделение", МассивНаименований);
// 5. Выполняем запрос
РезультатЗапроса = ЗапросCOM.Выполнить();
Если требуется выполнять сравнение по ссылочному полю (...Подразделение В (&Подразделение)), элементы отбора должны быть ссылками справочника внешней базы данных.
Для реализации этого подхода выполним поиск элементов во внешней базе по коду или GUID и заполним списковый объект контекста COM-соединения:
// Создаем список значений контекста внешнего соединения
СписокПодразделенийCOM = Connection1C.NewObject("СписокЗначений");
Для Каждого Стр Из ПолеСпискаПодразделений Цикл
Если Стр.Пометка Тогда
// Находим элемент справочника непосредственно во внешней базе по коду
СсылкаВнешняя = Connection1C.Справочники.ПодразделенияОрганизаций.НайтиПоКоду(Стр.Код);
Если ЗначениеЗаполнено(СсылкаВнешняя) Тогда
СписокПодразделенийCOM.Добавить(СсылкаВнешняя);
КонецЕсли;
КонецЕсли;
КонецЦикла;
ЗапросCOM = Connection1C.NewObject("Запрос");
// Условие сравнивает объект-ссылку с массивом/списком ссылок
ЗапросCOM.Текст =
"ВЫБРАТЬ
| ЗаказПокупателя.Ссылка КАК Ссылка
|ИЗ
| Документ.ЗаказПокупателя КАК ЗаказПокупателя
|ГДЕ
| ЗаказПокупателя.Подразделение В (&Подразделение)";
ЗапросCOM.УстановитьПараметр("Подразделение", СписокПодразделенийCOM);
РезультатЗапроса = ЗапросCOM.Выполнить();
.Наименование (тип Строка) со списком элементов СправочникСсылка.Запрос.Текст = ... должно выполняться перед вызовами методов УстановитьПараметр()..Количество() > 0 вместо функции ЗначениеЗаполнено().