При разработке на платформе 1С:Предприятие 8 с использованием Библиотеки стандартных подсистем (БСП) программисты часто сталкиваются с необходимостью быстро получить значения нескольких реквизитов объекта без его полной загрузки в память. Для этого в общем модуле ОбщегоНазначения предусмотрены две крайне похожие по названию, но разные по назначению функции: ЗначенияРеквизитовОбъекта и ЗначенияРеквизитовОбъектов. Ошибка в выборе нужной функции — одна из самых распространенных ловушек для новичков.
В этой статье мы разберем, почему возникает ошибка «Метод объекта не обнаружен (Количество)», проанализируем различия в типах возвращаемых данных и выясним, как эти функции помогают оптимизировать производительность системы.
Рассмотрим ситуацию, с которой столкнулся автор темы. Попытка вызвать метод для одного элемента справочника привела к аварийному завершению работы кода:
ДанныеИзделия = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(Элемент, "Код, Наименование");
Проблема здесь заключается в использовании функции во множественном числе (заканчивается на «Объектов»). Выясним причину ошибки: алгоритм функции ЗначенияРеквизитовОбъектов ожидает, что в первом параметре ей передадут коллекцию (Массив, Таблицу значений или Список значений). Внутри программного кода БСП первой же строкой идет проверка количества переданных ссылок:
Если Ссылки.Количество() = 0 Тогда
Возврат Новый Соответствие;
КонецЕсли;
Поскольку в переменную Элемент была передана одиночная ссылка, у которой нет метода Количество(), платформа выбрасывает исключение. Для работы с одной ссылкой необходимо использовать функцию в единственном числе.
Если нам нужно получить данные только по одному объекту (например, текущему элементу справочника), мы должны использовать функцию ЗначенияРеквизитовОбъекта. Рассмотрим правильный пример кода:
// Передаем одну ссылку и строку с именами реквизитов через запятую
ДанныеОбъекта = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаЭлемент, "Код, Артикул, Склад.Наименование");
// Результатом всегда будет Структура
Если ДанныеОбъекта.Артикул = "001" Тогда
Сообщить(ДанныеОбъекта.Наименование);
КонецЕсли;
Важный нюанс: функция всегда возвращает объект типа Структура. Если объект по ссылке не будет найден в базе данных, функция вернет структуру, в которой все запрашиваемые поля будут иметь значение Неопределено.
Когда стоит задача получить реквизиты сразу для множества ссылок (например, при обработке строк табличной части), использование циклов с одиночными запросами будет крайне неэффективным. В этом случае мы используем функцию во множественном числе. Разберем, как это работает на практике:
// Формируем массив ссылок
МассивСсылок = ТЧТовары.ВыгрузитьКолонку("Номенклатура");
// Получаем данные одним запросом к БД
ТаблицаДанных = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(МассивСсылок, "СтавкаНДС, ЕдиницаИзмерения");
// ВАЖНО: Результатом является Соответствие (Ключ - Ссылка, Значение - Структура реквизитов)
Для Каждого СсылкаИзСписка Из МассивСсылок Цикл
ДанныеНоменклатуры = ТаблицаДанных[СсылкаИзСписка];
Если ДанныеНоменклатуры <> Неопределено Тогда
// Работаем со структурой реквизитов конкретного объекта
ЗначениеНДС = ДанныеНоменклатуры.СтавкаНДС;
КонецЕсли;
КонецЦикла;
Проанализируем структуру результата: в отличие от версии для одного объекта, здесь возвращается Соответствие. Это позволяет мгновенно находить нужные данные по ключу-ссылке, что очень удобно при обходе больших массивов.
Одной из мощнейших особенностей этих функций БСП является поддержка получения данных через связанные поля. Посмотрим на пример:
"Склад.ОтветственноеЛицо.Наименование"
Если вы укажете такую строку в списке реквизитов, БСП автоматически построит сложный SQL-запрос с использованием левых соединений (LEFT JOIN). Это гораздо эффективнее, чем обращаться к таким полям напрямую в коде (например, Объект.Склад.ОтветственноеЛицо.Наименование), так как в последнем случае платформа будет последовательно подгружать в кэш три полных объекта, вместо того чтобы получить одно конкретное строковое значение.
Рассмотрим дополнительные параметры, которые могут быть полезны при разработке:
ВыбиратьРазрешенные. Если установить его в Истина, то при попытке прочитать реквизиты, на которые у пользователя нет прав (R-права), программа не упадет с ошибкой, а просто вернет Неопределено в соответствующих полях структуры.Пустая(), если это критично для логики."Намиенование" вместо "Наименование"), функция вызовет ошибку времени выполнения, так как не сможет найти такое поле в метаданных.Многие разработчики привыкли писать код вида Наименование = Ссылка.Наименование;. Выясним, почему в высоконагруженных системах это считается «плохим тоном»:
Ссылка.Реквизит платформа 1С считывает из базы данных весь объект целиком (все его реквизиты и даже табличные части) и помещает его в кэш. Если в объекте 100 реквизитов, а вам нужно только Наименование, вы нагружаете сеть и память сервера в десятки раз сильнее, чем нужно.ВЫБРАТЬ НужныеПоля ИЗ Справочник.Имя ГДЕ Ссылка = &Ссылка. В память попадают только те данные, которые вы явно перечислили в параметрах.Подводя итог, запомним простое правило: для одной ссылки используем ЗначенияРеквизитовОбъекта (результат — Структура), для многих ссылок — ЗначенияРеквизитовОбъектов (результат — Соответствие структур). Использование этих методов — признак профессионального подхода к разработке на платформе 1С.