В процессе разработки в 1С часто возникает задача обратиться из основной конфигурации к объектам, которые были добавлены в расширении. На первый взгляд, это должно работать без проблем, ведь платформа "склеивает" основную конфигурацию и подключенные расширения в единое целое. Однако на практике можно столкнуться с неочевидной ошибкой: "Ошибка при вызове метода контекста Выполнить()". Рассмотрим ситуацию, когда такой сбой происходит, и разберем, как его исправить.
Представим, что у нас есть основная конфигурация и стороннее расширение. В это расширение добавлен регистр сведений, например, Б24_К_ИдентификаторыДел. Нам нужно из общего серверного модуля основной конфигурации сделать запрос к этому регистру. Мы пишем код, проверяем его в консоли запросов — все работает. Но при запуске в коде получаем ту самую ошибку.
Первая мысль, которая может возникнуть: "основная конфигурация не видит таблицу из расширения". Но это предположение, как правило, неверно. Платформа 1С обеспечивает прозрачный доступ к объектам расширений, если они не скрыты намеренно. Проблема почти всегда кроется в деталях самого кода.
Давайте посмотрим на пример функции, которая вызывает ошибку. Задача функции — проверить, есть ли в регистре сведений запись, соответствующая определенному объекту.
Функция Б24_КБС_ПроверитьНаличиеСвязиСБ24(НастройкаПодключения, Б24_К_ОбъектДляЭкспорта) Экспорт
УстановитьПривилегированныйРежим(Истина);
// ... прочие действия ...
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Портал" , НастройкаПодключения.Портал);
Запрос.УстановитьПараметр("ТипыДанных" , Б24_К_RestApiВызовСервера.ПолучитьТипыДанныхДел());
Запрос.УстановитьПараметр("ТипОбъекта" , Б24_К_ОбъектДляЭкспорта.Метаданные().ПолноеИмя());
// !!! Проблемная строка
Запрос.УстановитьПараметр("ИдентификаторОбъекта", Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор());
Запрос.Текст = "ВЫБРАТЬ
| Б24_К_ИдентификаторыДел.ДополнительныйИдентификатор КАК Идентификатор
|ИЗ
| РегистрСведений.Б24_К_ИдентификаторыДел КАК Б24_К_ИдентификаторыДел
|ГДЕ
| Б24_К_ИдентификаторыДел.Портал = &Портал
| И Б24_К_ИдентификаторыДел.ТипДанных В(&ТипыДанных)
| И Б24_К_ИдентификаторыДел.ТипОбъекта = &ТипОбъекта
| И Б24_К_ИдентификаторыДел.ИдентификаторОбъекта = &ИдентификаторОбъекта";
// Ошибка возникает здесь
ВыполненныйЗапрос = Запрос.Выполнить();
Результат = НЕ ВыполненныйЗапрос.Пустой();
Возврат Результат;
КонецФункции
Ошибка "{<Неизвестный модуль>(1)}: Ошибка при вызове метода контекста Выполнить()" крайне неинформативна. Она говорит о том, что сбой произошел где-то внутри платформенного механизма выполнения запросов, и платформа не может сопоставить его с конкретной строкой вашего кода. Чаще всего это указывает на проблемы с параметрами запроса.
В чем же корень зла? Посмотрим внимательно на эту строку:
Запрос.УстановитьПараметр("ИдентификаторОбъекта", Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор());
Метод УникальныйИдентификатор() возвращает значение типа УникальныйИдентификатор. Это специальный объект, а не строка или число. В то же время, в регистре сведений поле ИдентификаторОбъекта, с которым происходит сравнение в условии ГДЕ, скорее всего, имеет тип Строка. Система запросов 1С не может напрямую сравнить объект типа УникальныйИдентификатор со значением в строковом поле таблицы базы данных. Это несоответствие типов и приводит к внутренней ошибке платформы при попытке выполнить запрос.
Решение простое и логичное: нужно передать в параметр запроса значение того же типа, что и у поля в таблице, с которым будет происходить сравнение. В нашем случае необходимо преобразовать уникальный идентификатор в строку.
Для этого воспользуемся функцией глобального контекста Строка().
Исправляем проблемную строку:
Запрос.УстановитьПараметр("ИдентификаторОбъекта", Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор());
Запрос.УстановитьПараметр("ИдентификаторОбъекта", <strong>Строка(</strong>Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор()<strong>)</strong>);
После этого простого исправления параметр &ИдентификаторОбъекта будет содержать строковое представление УИДа, и система запросов сможет корректно выполнить сравнение с полем в базе данных. Ошибка исчезнет.
Давайте посмотрим на полностью исправленный вариант функции. Теперь она будет работать надежно, не вызывая сбоев.
Функция Б24_КБС_ПроверитьНаличиеСвязиСБ24(НастройкаПодключения, Б24_К_ОбъектДляЭкспорта) Экспорт
УстановитьПривилегированныйРежим(Истина);
// ... прочие действия ...
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Портал" , НастройкаПодключения.Портал);
Запрос.УстановитьПараметр("ТипыДанных" , Б24_К_RestApiВызовСервера.ПолучитьТипыДанныхДел());
Запрос.УстановитьПараметр("ТипОбъекта" , Б24_К_ОбъектДляЭкспорта.Метаданные().ПолноеИмя());
// Исправленная строка с преобразованием типа
Запрос.УстановитьПараметр("ИдентификаторОбъекта", Строка(Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор()));
Запрос.Текст = "ВЫБРАТЬ
| Б24_К_ИдентификаторыДел.ДополнительныйИдентификатор КАК Идентификатор
|ИЗ
| РегистрСведений.Б24_К_ИдентификаторыДел КАК Б24_К_ИдентификаторыДел
|ГДЕ
| Б24_К_ИдентификаторыДел.Портал = &Портал
| И Б24_К_ИдентификаторыДел.ТипДанных В(&ТипыДанных)
| И Б24_К_ИдентификаторыДел.ТипОбъекта = &ТипОбъекта
| И Б24_К_ИдентификаторыДел.ИдентификаторОбъекта = &ИдентификаторОбъекта";
// Теперь выполнение запроса пройдет успешно
ВыполненныйЗапрос = Запрос.Выполнить();
Результат = НЕ ВыполненныйЗапрос.Пустой();
Возврат Результат;
КонецФункции
Запрос.Выполнить() в первую очередь проверяйте типы значений, которые вы передаете в параметры. Убедитесь, что они соответствуют типам полей, с которыми происходит сравнение в запросе.Запрос.Выполнить() поставьте точку останова и изучите значения и типы всех параметров в объекте Запрос. Это самый быстрый способ найти несоответствие.Строка().Следуя этим простым правилам, вы сможете избежать подобных неочевидных ошибок и сэкономить время на отладке.