При разработке в среде 1С:Предприятие одной из самых частых задач является получение значения конкретного реквизита справочника или документа по его ссылке. Начинающие разработчики часто используют прямое обращение через точку, однако в высоконагруженных системах или при работе с большими объектами этот подход становится критической ошибкой. В этой статье мы подробно разберем, как использовать механизмы Библиотеки стандартных подсистем (БСП) для эффективного решения этой задачи.
Рассмотрим стандартную ситуацию: у нас есть ссылка на элемент справочника, и нам нужно получить его наименование или какой-то специфический реквизит. Самый простой (и небезопасный) путь выглядит так:
// Неоптимальный способ
Значение = СсылкаНаОбъект.ИмяРеквизита;
Почему так делать нельзя? Проанализируем внутренние механизмы платформы. Когда вы обращаетесь к реквизиту через точку от ссылки, 1С выполняет неявное считывание всего объекта целиком из базы данных. Если в справочнике 50 реквизитов, несколько табличных частей и тяжелые хранилища значений (например, присоединенные файлы или картинки), система выгрузит их все в память сервера приложений. Это приводит к следующим последствиям:
Для решения описанной выше проблемы в БСП предусмотрен модуль ОбщегоНазначения. Рассмотрим подробнее функцию ЗначениеРеквизитаОбъекта. Она позволяет получить ровно одно поле, используя оптимизированный запрос к базе данных.
// Правильный способ получения одного реквизита
Значение = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаОбъект, "ИмяРеквизита");
Внутри этой функции БСП формирует запрос ВЫБРАТЬ ИмяРеквизита ИЗ Таблица ГДЕ Ссылка = &Ссылка. Это гарантирует минимальную нагрузку на систему.
Часто требуется получить не один, а два или три реквизита одного и того же объекта. Если вы трижды вызовете ЗначениеРеквизитаОбъекта, система выполнит три отдельных запроса к базе данных. Чтобы этого избежать, проанализируем функцию ЗначенияРеквизитовОбъекта (обратите внимание на множественное число в названии).
Эта функция принимает список реквизитов (строкой через запятую или массивом) и возвращает Структуру, где ключами являются имена реквизитов. Рассмотрим пример:
// Получение нескольких полей за один запрос
Реквизиты = "ИНН, КПП, НаименованиеПолное";
ДанныеКонтрагента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаКонтрагента, Реквизиты);
Если ДанныеКонтрагента.ИНН = "1234567890" Тогда
// выполняем логику
КонецЕсли;
Выясним причину, по которой этот метод удобнее ручного написания запроса. Функция БСП умеет работать с «путями» через точку. Например, вы можете запросить Владелец.Наименование, и БСП сама корректно обработает левое соединение таблиц в запросе.
Для тех, кто хочет глубже понять, как это работает «под капотом», приведем упрощенную логику того, что происходит внутри модуля ОбщегоНазначения. Это поможет осознать универсальность подхода:
Функция ЗначенияРеквизитовОбъекта(Ссылка, Знач Реквизиты) Экспорт
// 1. Преобразование строки в массив, если нужно
Если ТипЗнч(Реквизиты) = Тип("Строка") Тогда
Реквизиты = СтрРазделить(Реквизиты, ",", Ложь);
КонецЕсли;
// 2. Формирование текста полей запроса
ТекстПолей = "";
Для Каждого Реквизит Из Реквизиты Цикл
ТекстПолей = ТекстПолей + ?(ПустаяСтрока(ТекстПолей), "", ",") + Реквизит;
КонецЦикла;
// 3. Динамическое построение запроса
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.Текст = "ВЫБРАТЬ " + ТекстПолей + " ИЗ " + Ссылка.Метаданные().ПолноеИмя() + " ГДЕ Ссылка = &Ссылка";
// 4. Выполнение и заполнение структуры
Выборка = Запрос.Выполнить().Выбрать();
Результат = Новый Структура;
Если Выборка.Следующий() Тогда
ЗаполнитьЗначенияСвойств(Результат, Выборка);
КонецЕсли;
Возврат Результат;
КонецФункции
Самая большая ошибка производительности — вызов получения реквизитов внутри цикла по большому массиву ссылок. Это классическая проблема «N+1 запрос».
Проанализируем ситуацию: нам нужно вывести ИНН для 1000 контрагентов в отчете. Если мы вызовем ЗначениеРеквизитаОбъекта в цикле, мы получим 1000 обращений к БД. Для таких случаев в БСП существует функция ЗначенияРеквизитовОбъектов (в конце «в»).
Рассмотрим алгоритм работы:
Массив.Соответствие (Map), где ключом является Ссылка, а значением — Структура с данными.
// Оптимальная работа с массивом ссылок
МассивСсылок = СписокДокументов.ВыгрузитьКолонку("Ссылка");
ДанныеОбъектов = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(МассивСсылок, "Номер, Дата, СуммаДокумента");
Для Каждого Ссылка Из МассивСсылок Цикл
ТекущиеДанные = ДанныеОбъектов[Ссылка];
Если ТекущиеДанные <> Неопределено Тогда
Сообщить("Документ №" + ТекущиеДанные.Номер);
КонецЕсли;
КонецЦикла;
Иногда одни и те же данные (например, учетная политика организации или базовая валюта) требуются в коде постоянно. Чтобы не дергать базу данных даже оптимизированными запросами, в БСП есть модуль ОбщегоНазначенияПовтИсп.
Функции этого модуля кэшируют результат первого вызова в рамках сеанса. Повторный вызов функции ЗначениеРеквизитаОбъекта из этого модуля вернет данные мгновенно из оперативной памяти сервера.
Важно: используйте кэширование только для данных, которые гарантированно не изменятся в течение текущего сеанса пользователя.
Еще один важный нюанс, который мы должны рассмотреть — права доступа. Если у пользователя нет прав на просмотр справочника Контрагенты, обычный запрос или обращение через точку выдаст ошибку доступа. Однако функции БСП часто имеют параметры для выполнения в привилегированном режиме или уже находятся в привилегированных модулях. Это позволяет коду получить техническую информацию (например, признак «ПометкаУдаления») даже если пользователю запрещен доступ к самому объекту.
Подведем итоги нашего анализа. Для написания качественного кода на платформе 1С 8.3 следует придерживаться следующих правил:
ОбщегоНазначения.ЗначениеРеквизитаОбъекта для получения одиночных значений.ОбщегоНазначения.ЗначенияРеквизитовОбъекта для получения набора полей одного объекта.ОбщегоНазначения.ЗначенияРеквизитовОбъектов для пакетной обработки данных.ПовтИсп для часто запрашиваемых константных данных.Соблюдение этих простых правил сделает вашу конфигурацию быстрой, масштабируемой и соответствующей стандартам разработки фирмы «1С».