Как исправить ошибку "Выполнить()" при запросе к регистру из расширения в 1С?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

Представим, что у нас есть основная конфигурация и стороннее расширение. В это расширение добавлен регистр сведений, например, Б24_К_ИдентификаторыДел. Нам нужно из общего серверного модуля основной конфигурации сделать запрос к этому регистру. Мы пишем код, проверяем его в консоли запросов — все работает. Но при запуске в коде получаем ту самую ошибку.

Анализируем проблему и код

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

Давайте посмотрим на пример функции, которая вызывает ошибку. Задача функции — проверить, есть ли в регистре сведений запись, соответствующая определенному объекту.


Функция Б24_КБС_ПроверитьНаличиеСвязиСБ24(НастройкаПодключения, Б24_К_ОбъектДляЭкспорта) Экспорт
	
	УстановитьПривилегированныйРежим(Истина);

	// ... прочие действия ...

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

Ошибка "{<Неизвестный модуль>(1)}: Ошибка при вызове метода контекста Выполнить()" крайне неинформативна. Она говорит о том, что сбой произошел где-то внутри платформенного механизма выполнения запросов, и платформа не может сопоставить его с конкретной строкой вашего кода. Чаще всего это указывает на проблемы с параметрами запроса.

В чем же корень зла? Посмотрим внимательно на эту строку:

Запрос.УстановитьПараметр("ИдентификаторОбъекта", Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор());

Метод УникальныйИдентификатор() возвращает значение типа УникальныйИдентификатор. Это специальный объект, а не строка или число. В то же время, в регистре сведений поле ИдентификаторОбъекта, с которым происходит сравнение в условии ГДЕ, скорее всего, имеет тип Строка. Система запросов 1С не может напрямую сравнить объект типа УникальныйИдентификатор со значением в строковом поле таблицы базы данных. Это несоответствие типов и приводит к внутренней ошибке платформы при попытке выполнить запрос.

Находим и применяем решение

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

Для этого воспользуемся функцией глобального контекста Строка().

Исправляем проблемную строку:

  1. Было: Запрос.УстановитьПараметр("ИдентификаторОбъекта", Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор());
  2. Стало: Запрос.УстановитьПараметр("ИдентификаторОбъекта", <strong>Строка(</strong>Б24_К_ОбъектДляЭкспорта.Ссылка.УникальныйИдентификатор()<strong>)</strong>);

После этого простого исправления параметр &ИдентификаторОбъекта будет содержать строковое представление УИДа, и система запросов сможет корректно выполнить сравнение с полем в базе данных. Ошибка исчезнет.

Итоговый правильный код

Давайте посмотрим на полностью исправленный вариант функции. Теперь она будет работать надежно, не вызывая сбоев.


Функция Б24_КБС_ПроверитьНаличиеСвязиСБ24(НастройкаПодключения, Б24_К_ОбъектДляЭкспорта) Экспорт
	
	УстановитьПривилегированныйРежим(Истина);

	// ... прочие действия ...

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

Выводы и рекомендации

  1. Проверяйте типы данных. При возникновении ошибок в методе Запрос.Выполнить() в первую очередь проверяйте типы значений, которые вы передаете в параметры. Убедитесь, что они соответствуют типам полей, с которыми происходит сравнение в запросе.
  2. Используйте отладчик. Перед строкой Запрос.Выполнить() поставьте точку останова и изучите значения и типы всех параметров в объекте Запрос. Это самый быстрый способ найти несоответствие.
  3. Доступ к расширениям работает. Не сомневайтесь в базовой возможности платформы обращаться к объектам расширений из основной конфигурации. Если возникает ошибка, ищите проблему в своем коде, а не в архитектуре платформы.
  4. УникальныйИдентификатор — это объект. Всегда помните, что УИД — это не строка. Для использования его в сравнениях со строковыми полями, в текстовых файлах или при передаче через веб-сервисы, его нужно явно преобразовывать в строку с помощью Строка().

Следуя этим простым правилам, вы сможете избежать подобных неочевидных ошибок и сэкономить время на отладке.

← На главную