Как устроены менеджеры документов в 1С и почему важен контекст выполнения?

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

При изучении встроенного языка 1С начинающие разработчики часто сталкиваются с вопросами синтаксиса при обращении к документам. Например, почему обращение Выборка = Документы.УчебныйДень.Выбрать(); работает корректно, а попытки обратиться через «промежуточные» типы вроде Документы.ДокументВыборка... вызывают ошибки? В этой статье мы подробно разберем устройство прикладных объектов, иерархию менеджеров и правила работы в различных контекстах (клиент и сервер).

Иерархия менеджеров: Разбираем матрешку

Для начала проанализируем, что именно происходит, когда мы пишем слово Документы в программном коде. В системе 1С существует строгая иерархия объектов доступа к данным. Рассмотрим ее по шагам:

  1. Документы (тип DocumentsManager / ДокументыМенеджер): Это глобальный объект, который является «точкой входа». Его основная задача — предоставить доступ ко всем видам документов, которые вы создали в конфигураторе. Сами по себе Документы не умеют создавать конкретную запись или искать ее, они лишь содержат в себе коллекцию менеджеров конкретных типов.
  2. Документы.УчебныйДень (тип DocumentManager.[Имя] / ДокументМенеджер.[Имя]): Как только мы ставим точку после слова Документы и пишем имя конкретного метаобъекта (например, УчебныйДень), мы получаем доступ к менеджеру этого конкретного документа. Именно у этого объекта есть методы Выбрать(), СоздатьДокумент(), НайтиПоНомеру().

Разберем типичную ошибку: попытку написать Выборка = Документы.ДокументВыборка.УчебныйДень.Выбрать();. Выясним причину ошибки: ДокументВыборка — это не свойство глобального контекста и не контейнер. Это тип данных, который получается в результате работы метода Выбрать(). Мы не можем обращаться к менеджеру документа через тип выборки, так как это противоречит логике наследования и вложенности объектов в 1С.

Работа с менеджерами как с коллекцией

Посмотрим на пример, который помогает понять природу объекта Документы. Его можно представить как специализированную структуру или коллекцию. Рассмотрим код, имитирующий такое поведение:


// Создадим структуру для наглядности
СписокДокументМенеджеров = Новый Структура;

// Наполняем её ссылками на менеджеры конкретных документов
СписокДокументМенеджеров.Вставить("УчебныйДень", Документы.УчебныйДень);

// Теперь мы можем обращаться к методам менеджера через эту коллекцию
Выборка = СписокДокументМенеджеров["УчебныйДень"].Выбрать();

Проанализируем этот пример: использование квадратных скобок Документы["УчебныйДень"] позволяет обращаться к менеджерам динамически. Это крайне полезно, когда имя документа заранее неизвестно и передается в алгоритм в виде строки. Важно понимать: сам объект Документы «не знает» о методах конкретного документа (например, о специфических функциях, написанных в модуле менеджера), пока не будет произведено обращение к конкретному свойству (имени документа).

Три состояния прикладного объекта

Для глубокого понимания устройства 1С необходимо различать три основных формы существования документа в коде:

  1. Ссылка (DocumentRef): Это уникальный идентификатор записи (GUID). Она неизменяема, «весит» мало и доступна везде (и на клиенте, и на сервере).
  2. Объект (DocumentObject): Это данные документа, считанные в оперативную память для редактирования. Только у объекта есть метод Записать(). Работа с объектами возможна только на сервере.
  3. Выборка (DocumentSelection): Это динамический механизм (курсор) для последовательного обхода документов в базе данных. Она создается методом Выбрать() менеджера документа.

Проблема контекста: Почему код не работает на клиенте?

Часто программисты сталкиваются с ошибкой: Переменная не определена (Документы). Рассмотрим ситуацию: если вы напишете этот код в МодулеУправляемогоПриложения или в процедуре формы с директивой &НаКлиенте, система выдаст ошибку. Выясним, почему это происходит.

Объекты типа ДокументМенеджер напрямую работают с таблицами базы данных. В архитектуре «Тонкого клиента» прямой доступ к базе данных запрещен в целях безопасности и оптимизации трафика. Поэтому глобальный контекст Документы просто не существует на тонком клиенте. Чтобы код заработал, его необходимо перенести в процедуру с директивой &НаСервере или вызвать метод серверного общего модуля.

Пример правильного вызова:


&НаКлиенте
Процедура КомандаВыполнить(Команда)
    ПолучитьДанныеНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПолучитьДанныеНаСервере()
    // Здесь объект Документы доступен
    Выборка = Документы.УчебныйДень.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Обработка данных
    КонецЦикла;
КонецПроцедуры

Как платформа хранит документы «под капотом»

Разберем, как наши программные объекты превращаются в данные в СУБД (например, в MS SQL или PostgreSQL). Для платформы 1С каждый вид документа — это набор таблиц. ДокументМенеджер выступает в роли высокоуровневой обертки над SQL-запросами.

Когда мы вызываем метод Выбрать(), платформа транслирует это в SQL-запрос SELECT к соответствующей таблице. Если у документа есть табличные части, они хранятся в отдельных связанных таблицах. Таким образом, работа с прикладными объектами во встроенном языке — это удобный интерфейс, скрывающий от разработчика сложность прямых запросов к базе данных и обеспечивающий контроль прав доступа и целостность данных.

Метаданные против Менеджеров

Важно не путать обращение к данным и обращение к структуре. Рассмотрим разницу:

Документы.УчебныйДень используется для манипуляции данными: создать, найти, выбрать записи.

Метаданные.Документы.УчебныйДень используется для анализа структуры: программно узнать, какие у документа есть реквизиты, какова длина его номера или как называются его табличные части. Через Метаданные нельзя получить доступ к конкретным значениям в базе, только к описанию того, как эти значения должны выглядеть.

Резюмируем: понимание того, что Документы — это менеджер коллекции, доступный только на сервере, позволяет избежать большинства синтаксических ошибок и правильно проектировать архитектуру приложения, разделяя логику интерфейса и логику работы с данными.

← На главную