Как правильно описать тип колонки таблицы значений для хранения ролей в 1С:Предприятии 8.3?

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

При разработке функционала в 1С:Предприятии 8.3, особенно при работе с динамическими списками или отчетами, часто возникает необходимость хранить ссылки на различные объекты метаданных в программно создаваемых структурах, таких как таблицы значений (ТЗ). Одной из таких задач является создание колонки ТЗ, которая должна содержать ссылку на роль. Однако, прямая попытка описать тип колонки как Метаданные.Роли приводит к ошибке, поскольку конструктор ОписаниеТипов не поддерживает такой подход. В этом материале мы подробно разберем, почему возникает такая ошибка, и какие существуют надежные способы решения этой задачи, включая лучшие практики.

Давайте проанализируем исходную проблему. Когда вы пытаетесь использовать код вида:

ТТ = ОписаниеТипов("Метаданные.Роли");

вы сталкиваетесь с ошибкой. Причина заключается в том, что ОписаниеТипов не предназначен для непосредственного описания конкретных классов метаданных как типов данных для хранения в базе или в динамических коллекциях, передаваемых между клиентом и сервером. Объекты метаданных (такие как сами роли, справочники, документы как структуры) являются служебными объектами платформы, описывающими структуру конфигурации, но не являются типами, которые можно напрямую присвоить колонке таблицы значений для постоянного хранения или безопасной передачи.

Единственный «общий» тип, который может быть связан с объектами метаданных в памяти, это ОбъектМетаданных. Однако и он имеет серьезные ограничения:

  1. Доступность только в памяти: Тип ОбъектМетаданных существует только в контексте выполнения, и его нельзя использовать для описания колонок таблицы значений, если эта ТЗ предназначена для сохранения в базу данных или передачи между клиентом и сервером.
  2. Отсутствие сериализации: Объекты метаданных не всегда сериализуются, что делает их непригодными для передачи между клиентом и сервером, если они выступают как значения в колонках ТЗ. При попытке передачи такой ТЗ на клиент, вы, скорее всего, получите ошибку или потерю данных.

Исходя из этих ограничений, нам потребуются другие подходы для хранения ссылок на роли.

Решение 1: Использование строкового имени роли

Один из самых простых и часто используемых способов — это хранение полного строкового имени роли. Этот подход достаточно гибок и не требует использования дополнительных справочников, если в вашей конфигурации не используется Библиотека стандартных подсистем (БСП).

Как описать тип колонки

Для создания колонки, предназначенной для хранения имени роли, мы описываем ее как строковый тип:


ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("ИмяРоли", Новый ОписаниеТипов("Строка"));

В этом случае, в каждую ячейку колонки ИмяРоли мы будем записывать полное имя роли, например, "Администратор", "Бухгалтер" и так далее.

Программный выбор роли для пользователя

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

  1. Формирование списка значений на сервере: Создайте функцию на сервере, которая перебирает все доступные роли в конфигурации.
  2. Передача на клиент: Сформированный СписокЗначений (где значением будет имя роли, а представлением — синоним) можно передать на клиент, если это необходимо для интерактивного выбора.

Пример формирования списка ролей:


// Серверная функция
Функция ПолучитьСписокРолей()
    СписокРолей = Новый СписокЗначений;
    Для Каждого РольМетаданных Из Метаданные.Роли Цикл
        СписокРолей.Добавить(РольМетаданных.Имя, РольМетаданных.Синоним);
    КонецЦикла;
    Возврат СписокРолей;
КонецФункции

// Клиентский код (или серверный, если выбор происходит на сервере)
// Предполагаем, что СписокРолей уже получен с сервера
// ...
// Пример использования для заполнения элемента формы, например, поля выбора:
// Элементы.ПолеВыбораРоли.СписокВыбора = ПолучитьСписокРолей();
// ...

Преимущества и недостатки подхода со строкой

Преимущества:

  1. Простота реализации: Не требует использования дополнительных справочников или подсистем.
  2. Прямой доступ: Легко получить имя роли.

Недостатки:

  1. Проблема переименования: Если роль будет переименована в конфигураторе, строковое имя, хранящееся в ваших данных, устареет, и связь с реальной ролью будет потеряна. Это может привести к некорректной работе алгоритмов прав доступа или отображения информации.
  2. Отсутствие ссылочной целостности: Строка не является ссылкой, поэтому платформа не обеспечивает контроля целостности.
  3. Доступность метаданных: Объект Метаданные.Роли доступен только на сервере. Если вам нужен интерактивный выбор на клиенте, вам придется заранее формировать и передавать список имен или использовать серверные вызовы.

Решение 2: Использование справочника ИдентификаторыОбъектовМетаданных (БСП)

Этот подход является наиболее надежным и рекомендуемым, если в вашей конфигурации используется Библиотека стандартных подсистем (БСП). БСП предоставляет специализированный справочник ИдентификаторыОбъектовМетаданных, который предназначен для хранения ссылок на объекты метаданных конфигурации.

Как описать тип колонки

Для хранения ссылки на роль в ТЗ мы указываем тип колонки как ссылку на соответствующий справочник:


ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("СсылкаНаРоль", Новый ОписаниеТипов("СправочникСсылка.ИдентификаторыОбъектовМетаданных"));

Теперь в эту колонку мы можем записывать ссылки на элементы справочника ИдентификаторыОбъектовМетаданных, которые соответствуют нужным ролям.

Принцип работы справочника ИдентификаторыОбъектовМетаданных

  1. Хранение идентификаторов: Этот справочник содержит элементы, каждый из которых соответствует определенному объекту метаданных (справочнику, документу, отчету, роли и т.д.) вашей конфигурации.
  2. Автоматическое обновление: Чтобы роль появилась в этом справочнике, она должна быть либо явно отмечена в конфигураторе для индексации БСП, либо конфигурация должна пройти процедуру обновления вспомогательных данных (обычно выполняется автоматически после обновления конфигурации или при первом запуске).
  3. Надежная связь: Ссылка на элемент справочника обеспечивает надежную связь с объектом метаданных, даже если имя самого объекта будет изменено в конфигураторе. Справочник хранит внутренний уникальный идентификатор объекта метаданных.

Программный выбор роли и работа с данными

Для программного выбора ролей или работы с ними через этот справочник:

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

// Пример получения ссылки на идентификатор роли
// Предполагаем, что у вас есть общий модуль ОбщегоНазначенияБСП или аналог
// Вариант 1: Использование БСП-функции (если доступна)
ИдентификаторРоли = ОбщегоНазначенияБСП.ОбъектМетаданныхПоИмени("Роль.Администратор");

// Вариант 2: Запрос к справочнику
Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|    ИдентификаторыОбъектовМетаданных.Ссылка
|ИЗ
|    Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
|ГДЕ
|    ИдентификаторыОбъектовМетаданных.ПолноеИмя = &ПолноеИмя";

Запрос.УстановитьПараметр("ПолноеИмя", "Роль.Администратор");
РезультатЗапроса = Запрос.Выполнить();

Если НЕ РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    ИдентификаторРоли = Выборка.Ссылка;
КонецЕсли;

// Добавляем в ТЗ
// ТЗ.Добавить().СсылкаНаРоль = ИдентификаторРоли;

Коллизии с расширениями (ИдентификаторыОбъектовРасширений)

Важный нюанс при использовании справочника ИдентификаторыОбъектовМетаданных связан с расширениями конфигурации. В системе 1С может возникнуть ситуация, когда один и тот же объект метаданных (например, роль) присутствует как в основной конфигурации, так и в расширении. БСП обрабатывает такие ситуации, используя два разных справочника идентификаторов:

  1. Справочник.ИдентификаторыОбъектовМетаданных — для объектов основной конфигурации.
  2. Справочник.ИдентификаторыОбъектовРасширений — для объектов, добавленных или измененных через расширения.

Эта коллизия может привести к проблемам, если ваш программный код ищет роль только в основном справочнике, игнорируя расширения. В таком случае, роль, добавленная или модифицированная расширением, не будет найдена, что может привести к некорректному применению прав доступа или ошибкам в динамических алгоритмах. При работе с идентификаторами метаданных в расширенных конфигурациях всегда следует учитывать оба справочника или использовать универсальные функции БСП, которые умеют работать с объектами из расширений.

Преимущества и недостатки подхода с ИдентификаторыОбъектовМетаданных

Преимущества:

  1. Надежность и целостность: Обеспечивает ссылочную целостность. Переименование роли в конфигураторе не нарушит связь.
  2. Клиент-серверная безопасность: Ссылки на элементы справочника безопасно передаются между клиентом и сервером.
  3. Стандартное решение: Использует механизм, предусмотренный БСП, что облегчает поддержку и стандартизацию.

Недостатки:

  1. Зависимость от БСП: Требует наличия и корректной настройки Библиотеки стандартных подсистем.
  2. Дополнительные шаги: Требуется обеспечить попадание ролей в справочник (через обновление вспомогательных данных или пометку).
  3. Сложность с расширениями: Необходимость учета ИдентификаторыОбъектовРасширений и возможных "двойников".

Решение 3: Хранение нескольких ролей в одной ячейке ТЗ

Если вам требуется хранить не одну, а несколько ролей в одной ячейке таблицы значений (например, для описания набора ролей, необходимых для определенного действия), мы сталкиваемся с тем, что ОписаниеТипов не позволяет создать тип колонки "МассивРолей". В таких случаях мы можем использовать следующие подходы:

  1. Строка с разделителями: Самый простой способ — это хранить имена ролей в виде одной строки, разделяя их каким-либо символом (например, запятой, точкой с запятой). При получении данных, строку нужно будет разобрать на отдельные имена.
  2. 
    ТЗ.Колонки.Добавить("НаборРолей", Новый ОписаниеТипов("Строка"));
    // ...
    // Запись: "Администратор,Бухгалтер,Менеджер"
    
  3. ХранилищеЗначения: Для более сложных структур, таких как массив ссылок на ИдентификаторыОбъектовМетаданных или массив строк с именами ролей, можно использовать тип ХранилищеЗначения. Этот тип позволяет сериализовать и хранить в базе данных произвольные значения 1С, включая массивы, структуры и коллекции.
  4. 
    ТЗ.Колонки.Добавить("НаборРолейОбъектом", Новый ОписаниеТипов("ХранилищеЗначения"));
    // ...
    // Создаем массив, который будет храниться в ХранилищеЗначения
    МассивРолейДляХранения = Новый Массив;
    МассивРолейДляХранения.Добавить(ИдентификаторРолиАдминистратор);
    МассивРолейДляХранения.Добавить(ИдентификаторРолиБухгалтер);
        
    // Записываем в колонку
    // ТЗ.Добавить().НаборРолейОбъектом = Новый ХранилищеЗначения(МассивРолейДляХранения);
    

    При использовании ХранилищеЗначения помните, что для получения исходного значения из него потребуется выполнить операцию "получить".

Общие рекомендации и выводы

Исходя из рассмотренных подходов, мы можем сформулировать следующие рекомендации:

  1. Избегайте прямых ссылок на Метаданные.Роли: Ни при каких обстоятельствах не пытайтесь использовать ОписаниеТипов("Метаданные.Роли") или напрямую передавать объекты Метаданные.Роли через клиент-серверные границы. Это приведет к ошибкам и ненадежной работе.
  2. Используйте СправочникСсылка.ИдентификаторыОбъектовМетаданных: Если у вас есть БСП, это самый надежный и рекомендуемый способ хранения ссылок на роли. Он обеспечивает стабильность и целостность данных. Не забывайте о возможности ИдентификаторыОбъектовРасширений.
  3. Строка как альтернатива: Если БСП не используется или задача очень проста, хранение строкового имени роли является приемлемым, но менее надежным вариантом из-за рисков переименования.
  4. Клиент-серверные взаимодействия: Всегда помните, что коллекция Метаданные доступна только на сервере. Формирование списков для выбора на клиенте должно производиться на сервере с последующей передачей безопасных для клиента типов данных (строки, списки значений, ссылки на справочники).

Правильный выбор подхода зависит от требований к надежности, масштабируемости и используемых в конфигурации подсистем. Мы всегда рекомендуем придерживаться стандартных механизмов платформы и библиотек, таких как БСП, для обеспечения устойчивости и простоты поддержки вашей системы.

← На главную