Как исправить ошибку проверки пустой ссылки и структуры метаданных в COM-запросе 1С

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

При организации интеграции между базами данных 1С с использованием COM-соединения разработчики нередко сталкиваются с ошибками синтаксического анализа запроса. Типичными симптомами являются сообщения вида «Неверные параметры "Документ.ЗаказПоставщику.ПустаяСсылка"» или «Поле не найдено "ПоступлениеТоваровУслуг.ЗаказПоставщику"», несмотря на то, что в структуре целевой информационной базы указанные объекты и реквизиты точно существуют. Разберем по шагам, почему возникают такие ситуации, как выявить скрытые логические ошибки при инициализации объектов и как правильно организовать фильтрацию по пустым ссылкам во внешних базах.

Причина 1: Случайная перезапись COM-объекта локальным конструктором

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


// Создание COM-объекта в удаленной базе
Запрос = Ком.NewObject("Запрос");

// Случайная перезапись переменной локальным объектом
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Дата1", НачалоДня(ДатаС));
Запрос.УстановитьПараметр("Дата2", КонецДня(ДатаПо));

В приведенном примере вторая строка Запрос = Новый Запрос; полностью перетирает ссылку на удаленный запрос Ком.NewObject("Запрос"). В результате последующий вызов метода Выполнить() происходит не в удаленной базе-приемнике, а в текущей базе-источнике. Если в текущей конфигурации нет документа ЗаказПоставщику или у документа ПоступлениеТоваровУслуг отсутствует данный реквизит, платформа выдаст ошибку отсутствия метаданных или неверного значения функции ЗНАЧЕНИЕ(...).

Для исправления ситуации необходимо убрать лишнюю локальную инициализацию и передавать параметры строго в объект удаленной базы:


// Корректная инициализация запроса в контексте внешней базы
Запрос = Ком.NewObject("Запрос");
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Поступление.Ссылка,
    |    Поступление.Организация,
    |    Поступление.Контрагент
    |ИЗ
    |    Документ.ПоступлениеТоваровУслуг КАК Поступление
    |ГДЕ
    |    Поступление.Дата МЕЖДУ &Дата1 И &Дата2
    |    И НЕ Поступление.ЗаказПоставщику = ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)";

Запрос.УстановитьПараметр("Дата1", НачалоДня(ДатаС));
Запрос.УстановитьПараметр("Дата2", КонецДня(ДатаПо));

РезультатЗапроса = Запрос.Выполнить();

Причина 2: Проверка пустых ссылок через параметры COM-запроса

В ряде сценариев конструкция ЗНАЧЕНИЕ(...) внутри текста запроса может быть нежелательна, особенно если тип метаданных динамически подставляется или реквизит является составным. В этом случае пустую ссылку можно передать в качестве параметра. Посмотрим, как корректно получить пустую ссылку из внешнего соединения:

  1. Обратимся к менеджеру документа через COM-соединение: метод ПустаяСсылка() должен вызываться именно у менеджера внешней базы.
  2. Передадим полученное внешнее значение в параметр COM-запроса.

Рассмотрим пример кода:


// Получаем пустую ссылку из целевой конфигурации
ПустаяСсылкаЗаказ = Ком.Документы.ЗаказПоставщику.ПустаяСсылка();

Запрос = Ком.NewObject("Запрос");
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Поступление.Ссылка КАК Ссылка
    |ИЗ
    |    Документ.ПоступлениеТоваровУслуг КАК Поступление
    |ГДЕ
    |    НЕ Поступление.ЗаказПоставщику = &ПустаяСсылка";

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

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

Особенности проверки заполненности для составных типов данных

Если реквизит шапки или табличной части имеет составной тип (например, ссылается на несколько разных типов документов заказов), простая проверка НЕ Поле = ЗНАЧЕНИЕ(...) может сработать некорректно. В незаполненном поле составного типа может храниться системное значение Неопределено либо пустая ссылка другого вида документа.

Разберем способы корректной фильтрации таких полей:

  1. Проверка на совпадение типа и непустую ссылку:

    Используем предикат ССЫЛКА совместно с проверкой на неравенство пустой ссылке нужного вида документа:

    
    ГДЕ
        Поступление.ЗаказПоставщику ССЫЛКА Документ.ЗаказПоставщику
        И НЕ Поступление.ЗаказПоставщику = ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)
    
  2. Использование операции ВЫРАЗИТЬ:

    Для оптимизации обращения к реквизиту составного типа приведем его к конкретному типу метаданных с помощью функции ВЫРАЗИТЬ. Это исключает неявные соединения с таблицами других документов, входящих в составной тип:

    
    ГДЕ
        НЕ ВЫРАЗИТЬ(Поступление.ЗаказПоставщику КАК Документ.ЗаказПоставщику) = ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)
        И НЕ Поступление.ЗаказПоставщику ЕСТЬ NULL
    

Чек-лист диагностики проблем с внешними COM-запросами

Если запрос продолжает выдавать ошибки структуры метаданных при подключении через V83.COMConnector, выполним следующие контрольные шаги:

  1. Проверка прав учетной записи: убедимся, что у пользователя, указанного в строке подключения, назначена роль с правом «Внешнее подключение», а также имеются полные права на чтение требуемых таблиц и реквизитов. Наличие ограничений RLS (доступ на уровне записей) может визуально выглядеть как отсутствие данных или приводить к исключениям при нехватке прав на метаданные.
  2. Проверка строки соединения: убедимся, что параметры Srvr и Ref (или File) указывают именно на внешнюю информационную базу, а не на текущую базу данных.
  3. Расположение реквизита: проверим в конфигураторе удаленной базы, где физически расположен реквизит — в шапке документа или в его табличной части. Попытка обратиться к реквизиту табличной части напрямую через обращение к таблице документа (без указания имени табличной части) всегда вызывает ошибку «Поле не найдено».
← На главную