При разработке прикладных решений на платформе 1С программисты часто сталкиваются с необходимостью создания временных или постоянных хранилищ данных, которые выполняют роль «корзины», «буфера обмена» или «списка избранного». Одним из наиболее подходящих объектов для этой задачи является регистр сведений. Однако ключевой вопрос заключается в его структуре: какие поля должны быть измерениями, а какие — ресурсами? От этого выбора зависит не только корректность работы логики, но и производительность всей системы.
В данной статье мы подробно разберем, как правильно организовать структуру регистра для реализации «буфера обмена» объектами (например, контрагентами), проанализируем влияние уникальности записей на бизнес-логику и рассмотрим альтернативные варианты реализации этой задачи.
Прежде всего, давайте выясним фундаментальное различие между измерениями и ресурсами в регистре сведений. В 1С совокупность всех измерений (и периода, если регистр периодический) составляет ключ записи. Это означает, что в системе не может существовать двух записей с абсолютно одинаковыми значениями во всех измерениях.
Рассмотрим ситуацию, описанную в вопросе: нам нужно хранить список контрагентов, которых пользователь «отложил» для дальнейшей обработки (например, для массового формирования счетов).
Вариант 1: Одно измерение (Пользователь) и один ресурс (Контрагент)
Если мы установим Пользователь как единственное измерение, а Контрагент — как ресурс, то ключом записи будет только поле Пользователь. Проанализируем последствия:
Такой подход реализует связь «один-к-одному». Он удобен, если вам нужно хранить, например, «последнего выбранного контрагента», но совершенно не подходит для создания списка или «буфера».
Вариант 2: Два измерения (Пользователь и Контрагент)
В этом случае ключом записи является комбинация этих двух полей. Это позволяет реализовать связь «многие-ко-многим»:
Проанализируем ситуацию: это именно то, что требуется для реализации функционала «корзины». Таким образом, правильным решением для хранения списка будет использование обоих полей в качестве измерений. Ресурсов в таком регистре может не быть вовсе, если нам не нужно хранить дополнительные данные (например, количество или примечание).
При проектировании регистра сведений крайне важно обратить внимание на свойство «Ведущее» у измерений. Рассмотрим, как это работает в нашем примере с буфером:
Если мы пометим измерение Пользователь как Ведущее, то при удалении пользователя из справочника Пользователи система автоматически очистит все записи в регистре, связанные с этим пользователем. Это избавляет базу данных от «мусора» и записей, которые больше никогда не будут востребованы.
Аналогично, если мы сделаем измерение Контрагент ведущим, то при удалении контрагента (или пометке на удаление с последующей очисткой) запись в буфере также исчезнет. Это предотвращает появление в интерфейсе пользователя пустых строк или сообщений об ошибке <Объект не найден>.
Платформа 1С автоматически создает индексы по измерениям регистра сведений. Однако эффективность этих индексов напрямую зависит от порядка следования измерений в метаданных. Разберем этот момент подробнее:
Если ваша основная задача — быстро получать список всех контрагентов для текущего пользователя, то измерение Пользователь должно стоять первым в списке измерений регистра. В этом случае поиск по индексу будет мгновенным.
Если же вы сделаете Пользователя ресурсом (как предлагалось в одном из вариантов вопроса), то для получения списка объектов конкретного сотрудника системе придется выполнить полное сканирование всей таблицы регистра (Full Scan), что при большом количестве пользователей и записей приведет к существенным задержкам.
В процессе обсуждения на форуме возникла интересная идея: а не использовать ли для этих целей Документ? Давайте проанализируем, в каких ситуациях это может быть оправдано.
Использование документа с табличной частью Контрагенты дает следующие преимущества:
Однако для оперативного «тыканья» в списке (быстрого добавления элементов) документ подходит меньше, так как требует постоянной записи и блокировок объекта. Регистр сведений в данном случае — более «легковесный» и быстрый инструмент.
Рассмотрим, как может выглядеть код для добавления элемента в такой регистр и последующего получения списка. Предположим, наш регистр называется БуферОбменаОбъектами с измерениями Пользователь и Объект.
Добавление записи:
МенеджерЗаписи = РегистрыСведений.БуферОбменаОбъектами.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Пользователь = ПараметрыСеанса.ТекущийПользователь;
МенеджерЗаписи.Объект = ВыбранныйКонтрагент;
// Пытаемся записать. Если такая запись уже есть, ошибки не будет, она просто обновится.
МенеджерЗаписи.Записать(Истина);
Получение списка всех объектов пользователя через запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Буфер.Объект КАК Контрагент
|ИЗ
| РегистрСведений.БуферОбменаОбъектами КАК Буфер
|ГДЕ
| Буфер.Пользователь = &ТекущийПользователь";
Запрос.УстановитьПараметр("ТекущийПользователь", ПараметрыСеанса.ТекущийПользователь);
РезультатЗапроса = Запрос.Выполнить();
Поскольку регистр сведений — это физическая таблица в базе данных, данные в нем хранятся постоянно. В отличие от временных таблиц в запросах или временного хранилища (в 8.3), записи в регистре «буфера» сами не исчезнут.
Рассмотрим рекомендации по обслуживанию такого регистра:
ДатаДобавления. Настройте регламентное задание, которое раз в сутки будет удалять записи, созданные более 2–3 дней назад.Выясним, как менялись подходы к реализации подобного функционала с развитием 1С:
ПоместитьВоВременноеХранилище(). Это избавит базу данных от лишней нагрузки.Резюме: Если вы создаете «корзину» или «список объектов для обработки» на базе регистра сведений, делайте и Пользователя, и Объект измерениями. Это обеспечит правильную работу со списками, а установка свойства «Ведущее» и правильный порядок измерений гарантируют целостность данных и высокую скорость работы системы.