Как правильно и эффективно получать значения реквизитов через точку в 1С

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

В практике разработки на платформе 1С:Предприятие 8 часто возникает вопрос: насколько корректно получать данные, обращаясь к реквизитам через «точку» (разыменование ссылок)? Этот метод кажется интуитивно понятным и простым, однако за ним скрываются механизмы, которые могут существенно повлиять на производительность системы и стабильность кода. В этой статье мы подробно разберем, как работает обращение через точку в запросах и в программном коде, когда это допустимо, а когда стоит использовать альтернативные методы.

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

Для начала проанализируем, что происходит «под капотом» платформы, когда мы пишем запрос с обращением через точку. Рассмотрим пример кода из обсуждения:


Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    СчетНаОплатуПокупателю.ДоговорКонтрагента.бит_стр_Строительство.бит_стр_Проект КАК Проект
               |ИЗ
               |    Документ.СчетНаОплатуПокупателю КАК СчетНаОплатуПокупателю
               |ГДЕ
               |    СчетНаОплатуПокупателю.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Основание);

Когда этот запрос передается на уровень СУБД (SQL Server, PostgreSQL и др.), платформа 1С автоматически преобразует каждое обращение через точку в ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN). В данном примере будет создано как минимум три соединения: со справочником договоров, затем с таблицей, на которую ссылается реквизит бит_стр_Строительство, и, наконец, с таблицей проектов.

Важные выводы из этого механизма:

  1. Количество соединений: Чем длиннее цепочка точек, тем больше таблиц объединяет SQL-сервер. Слишком длинные цепочки (более 3-4 уровней) могут усложнить план выполнения запроса и замедлить его.
  2. Результат при пустых ссылках: Поскольку используется LEFT JOIN, если на любом этапе цепочки встретится пустая ссылка или значение NULL, итоговый результат также будет NULL. Это поведение безопасно и не вызывает исключительных ситуаций в самом запросе.
  3. Индексация: Помните, что для быстродействия таких запросов поля, по которым происходит соединение (ссылочные поля), должны быть индексированы. Платформа 1С делает это автоматически для стандартных реквизитов, но при работе с дополнительными реквизитами стоит проверять настройки индексирования.

Работа с составными типами данных и оператор ВЫРАЗИТЬ

Проанализируем ситуацию, когда один из реквизитов в цепочке имеет составной тип данных. Это критический момент для производительности. Если реквизит может содержать ссылки, например, на 10 различных видов документов, то обращение через точку без уточнения типа заставит платформу выполнить LEFT JOIN со всеми 10 таблицами одновременно.

Чтобы избежать колоссальной нагрузки на СУБД, необходимо использовать оператор ВЫРАЗИТЬ. Посмотрим на примере, как ограничить выборку конкретным типом:


// Предположим, ДоговорКонтрагента имеет составной тип
Запрос.Текст = "ВЫБРАТЬ
               |    ВЫРАЗИТЬ(Счет.ДоговорКонтрагента КАК Справочник.ДоговорыКонтрагентов).Код КАК КодДоговора
               |ИЗ
               |    Документ.СчетНаОплатуПокупателю КАК Счет";

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

Использование функций БСП для получения реквизитов

Если нам нужно получить значение реквизита в программном коде (на языке 1С), а не внутри сложного запроса, рассмотрим использование функций Библиотеки Стандартных Подсистем (БСП). В модуле ОбщегоНазначения существуют специальные методы для этих целей. Для быстрого поиска готовых конструкций и функций библиотеки пригодится справочник по методам БСП с примерами вызова.

Разберем основные преимущества метода ОбщегоНазначения.ЗначениеРеквизитаОбъекта():

  1. Безопасность: Метод корректно обрабатывает передачу пустых ссылок и объектов, помеченных на удаление, не вызывая ошибок «Поле объекта не обнаружено».
  2. Кэширование: В современных версиях БСП реализовано кэширование, что позволяет избежать повторных запросов к базе данных, если один и тот же реквизит считывается несколько раз в рамках одного серверного вызова.
  3. Удобство обращения: Вы также можете передавать строку с именами реквизитов через точку.

Пример использования функции БСП:


// Получение одного значения
Проект = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Основание, "ДоговорКонтрагента.бит_стр_Строительство.бит_стр_Проект");

// Массовое получение (рекомендуется для списков)
СтруктураРеквизитов = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаОбъект, "Организация, Склад, ВалютаДокумента");

Важное уточнение: Если вам нужно получить данные для списка объектов (например, в цикле при обработке строк), никогда не вызывайте получение реквизитов в цикле. Вместо этого используйте метод ЗначенияРеквизитовОбъектов() (во множественном числе), который выполнит один запрос ко всем ссылкам сразу.

Чего следует избегать: Ссылка.ПолучитьОбъект()

Выясним причину, по которой крайне не рекомендуется использовать метод ПолучитьОбъект() для простого чтения реквизитов. Рассмотрим плохой пример:


// НЕПРАВИЛЬНО:
ИмяПроекта = СсылкаНаСчет.ПолучитьОбъект().ДоговорКонтрагента.бит_стр_Проект;

Почему это плохо:

Всегда отдавайте предпочтение запросам или функциям ОбщегоНазначения, если объект не требуется для изменения и записи.

Рациональный выбор метода: когда и что использовать?

Проанализируем ситуацию с точки зрения архитектурных стандартов 1С. Выбор способа получения данных зависит от контекста задачи:

1. Обращение через точку в запросе

Когда использовать: При подготовке данных для отчетов, динамических списков или проведении документов, когда данные нужны массово.

Ограничения: Не делайте цепочки длиннее 3-4 колен. Если цепочка становится слишком сложной, лучше использовать явное ЛЕВОЕ СОЕДИНЕНИЕ в конструкторе запроса — это сделает ваш код более читаемым для других разработчиков.

2. Функции БСП (ОбщегоНазначения)

Когда использовать: В программном коде для получения 1-2 значений, когда написание полноценного запроса кажется избыточным, или когда важна защита от пустых ссылок.

3. Прямое обращение через точку в коде (Ссылка.Реквизит1.Реквизит2)

Когда использовать: Допустимо только в простых сценариях «на лету», если вы абсолютно уверены, что типы не составные, а объем данных крайне мал (например, в формах при интерактивной работе пользователя). Однако помните, что каждое такое обращение — это неявный и не всегда оптимальный запрос к базе данных.

Итоги и рекомендации

Подводя итог нашему анализу, сформулируем основные правила работы с реквизитами через точку:

  1. Для простых типов: Обращение через точку в запросе абсолютно корректно и эквивалентно соединению таблиц.
  2. Для составных типов: Всегда используйте ВЫРАЗИТЬ(Поле КАК Тип), чтобы ограничить количество соединений на уровне SQL.
  3. Для массовой обработки: Всегда используйте запросы. Избегайте получения реквизитов в циклах.
  4. Для безопасности: Используйте методы БСП ОбщегоНазначения, чтобы избежать падений системы при обращении к «битым» ссылкам.
  5. Права доступа (RLS): Помните, что обращение через точку учитывает ограничения RLS. Если прав на связанный справочник нет, вы получите NULL даже при наличии прав на основной объект.

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

← На главную