При разработке интеграционных решений, таких как HTTP-сервисы, программисты часто сталкиваются с ситуациями, когда данные, полученные из запросов к базе данных, ведут себя непредсказуемо. Особенно это актуально для конфигураций, работающих в режиме совместимости (например, ЗУП 2.5 на платформе 8.3), где пересекаются старые методы работы и новые механизмы платформы. В данной статье мы разберем, как устранить ошибки сравнения несовпадающих примитивных типов и что делать, если система сообщает: «Значение не является значением объектного типа (Метаданные)».
Рассмотрим ситуацию: при обходе выборки запроса возникает исключение Операции сравнения на больше-меньше допустимы только для значений совпадающих примитивных типов (Булево, Число, Строка, Дата). Проанализируем типичный фрагмент кода, где это происходит:
// Ошибка возникает здесь
Если Выборка.ДатаПриемаНаРаботу > ДатаЗапроса Тогда
Продолжить;
КонецЕсли;
Выясним причину этой ошибки. В языке запросов 1С, если в тексте используется ЛЕВОЕ СОЕДИНЕНИЕ, и для записи из левой таблицы не найдено соответствия в правой, поля правой таблицы принимают значение NULL. Тип NULL не является датой, числом или строкой. Попытка сравнить NULL с объектом типа Дата (в нашем случае ДатаЗапроса) приводит к аварийному завершению работы кода, так как платформа не может сопоставить эти типы.
Самый быстрый способ исправить ситуацию непосредственно в цикле обхода выборки — добавить явную проверку на заполненность поля. Мы должны убедиться, что значение не является NULL, прежде чем выполнять сравнение. Перепишем условие следующим образом:
Пока Выборка.Следующий() Цикл
// Добавляем проверку на NULL
Если Выборка.ДатаПриемаНаРаботу <> NULL И Выборка.ДатаПриемаНаРаботу > ДатаЗапроса Тогда
Продолжить;
КонецЕсли;
// Дальнейшая обработка данных
КонецЦикла;
Важный момент: в 1С операция сравнения <> NULL позволяет отсечь пустые значения, пришедшие из соединений таблиц, и предотвратить ошибку несовпадения типов.
Как справедливо замечают опытные разработчики, в целях повышения производительности лучше переносить условия фильтрации в сам запрос, а не обрабатывать их в цикле. Если мы не хотим получать NULL в выборке, воспользуемся функцией ЕСТЬNULL в тексте запроса. Это позволит нам сразу назначить «пустую» дату или другое значение по умолчанию.
Разберем пример корректировки текста запроса:
Запрос.Текст = "
|ВЫБРАТЬ
| СотрудникиОрганизаций.Ссылка КАК Сотрудник,
| ЕСТЬNULL(СотрудникиОрганизаций.ДатаПриемаНаРаботу, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаПриема
|ИЗ
| Справочник.СотрудникиОрганизаций КАК СотрудникиОрганизаций
|ГДЕ
| СотрудникиОрганизаций.ДатаПриемаНаРаботу <= &ДатаЗапроса";
Используя конструкцию ГДЕ в запросе, мы существенно сокращаем объем данных, передаваемых из базы в оперативную память сервера. Это критически важно при работе с HTTP-сервисами, где скорость ответа является ключевым показателем.
Вторая распространенная ошибка — Значение не является значением объектного типа (Метаданные). Чаще всего она встречается в самописных функциях получения имени перечисления, например:
Функция обИмяПеречисления(Ссылка) Экспорт
ИмяПеречисления = Ссылка.Метаданные().Имя; // Здесь происходит ошибка
Индекс = Перечисления[ИмяПеречисления].Индекс(Ссылка);
Возврат Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления[Индекс].Имя;
КонецФункции
Проанализируем ситуацию: если в функцию передается значение NULL (например, из той же выборки запроса, где не заполнено поле перечисления), у него невозможно вызвать метод Метаданные(). Тип NULL — это не ссылка на объект базы данных.
Чтобы избежать этой ошибки, выполним два шага:
ЗначениеЗаполнено(Ссылка).XMLСтрока(). Он работает со ссылками напрямую и возвращает строковое имя значения (например, "ОсновноеМестоРаботы") без обращения к метаданным.Посмотрим на улучшенный вариант функции:
Функция обИмяПеречисления(Ссылка) Экспорт
Если Не ЗначениеЗаполнено(Ссылка) Тогда
Возврат "";
КонецЕсли;
// Метод XMLСтрока для перечислений возвращает Имя значения в конфигураторе
Возврат XMLСтрока(Ссылка);
КонецФункции
При формировании ответа в формате JSON важно помнить о типах данных. Поля структуры, которая затем сериализуется в JSON, должны содержать только примитивные типы (Строка, Число, Булево, Дата). Ссылки (СправочникСсылка, ПеречислениеСсылка) и значения NULL должны быть преобразованы заранее.
Проанализируем несколько советов по оптимизации:
Строка(Ссылка.УникальныйИдентификатор()).null (в понимании JSON).ЗаписьJSON. Это работает значительно быстрее, чем ручная склейка строк.Разберем пример правильного формирования структуры перед отправкой:
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("Guid", Строка(Выборка.Сотрудник.УникальныйИдентификатор()));
СтруктураДанных.Вставить("Name", Выборка.ФИО);
// Обрабатываем NULL для строковых полей
СтруктураДанных.Вставить("Position", ?(Выборка.Должность = NULL, "", Строка(Выборка.Должность)));
Следуя этим правилам, мы не только избавимся от ошибок выполнения кода, но и сделаем наш HTTP-сервис более стабильным и производительным. Помните, что аккуратная обработка типов данных — залог отсутствия «необъяснимых» падений системы при изменении данных в базе.