При разработке конфигураций на платформе 1С:Предприятие одной из самых частых проблем начинающих разработчиков является непонимание принципов формирования уникальности записей в регистрах сведений. Проблема проявляется в виде системной ошибки: «Запись с такими ключевыми полями уже существует». В этой статье мы подробно разберем, почему возникает эта ситуация, и как правильно спроектировать структуру регистра для хранения иерархических или связанных данных.
Рассмотрим ситуацию: у нас есть регистр сведений, предназначенный для хранения информации о согласованиях чертежей. Структура регистра изначально была спроектирована следующим образом:
Объект (СправочникСсылка.Объекты) — ИзмерениеКомплектЧертежей (СправочникСсылка.КомплектыЧертежей) — ИзмерениеПереченьСогласований (СправочникСсылка.ПереченьСогласований) — РесурсДатаНачала (Дата) — РесурсДатаОкончания (Дата) — РесурсПроанализируем логику: разработчик хочет, чтобы для одного «Объекта» и одного «Комплекта» можно было добавить несколько «Согласований». Однако при попытке записи второго согласования система выдает ошибку. Выясним причину: в 1С уникальность записи в непериодическом регистре определяется исключительно набором значений его измерений. Этот набор называется Ключом записи.
В текущей структуре ключом является комбинация Объект + КомплектЧертежей. Если в базе уже есть запись для «Объекта А» и «Комплекта 1», то любая новая попытка записать данные по этим же координатам (даже с другим согласованием в ресурсах) будет восприниматься системой как попытка изменить существующую строку, а не создать новую. Если же запись производится через МенеджерЗаписи с установленным признаком обмена или специфическими методами набора, платформа выдаст ошибку неуникальности.
Самый простой и логичный способ решить проблему — сделать поле ПереченьСогласований измерением. Разберем, как изменится ситуация:
Теперь ключ записи будет состоять из трех полей: Объект + КомплектЧертежей + ПереченьСогласований. Это позволит нам хранить в регистре следующие строки:
Важно: этот метод подходит, если для одного комплекта одно и то же согласование не может повторяться дважды. Если же вам нужно хранить историю повторных согласований одного и того же типа, этот метод потребует дополнительного измерения (например, НомерПопытки или ДатаНачала в измерениях).
Если данные в регистре имеют временную природу, мы можем проанализировать ситуацию и сделать регистр периодическим. Посмотрим, как это повлияет на уникальность:
В периодическом регистре к ключу записи (измерениям) автоматически добавляется поле Период. Это позволяет хранить одинаковые комбинации Объект + КомплектЧертежей, но на разные даты. Однако стоит помнить:
Рассмотрим более сложный, но архитектурно правильный подход при больших объемах данных. Хранение «Объекта» в каждой строке согласования может привести к избыточности. Проанализируем вариант разделения на два регистра:
Регистр №1: Состав комплектов объектов
КомплектЧертежейОбъектРегистр №2: Ход согласований
КомплектЧертежейСогласованиеДатаНачала, ДатаОкончанияТакой подход позволяет избежать дублирования информации об объекте в каждой строке согласования. Объект «привязан» к комплекту один раз в первом регистре, а во втором мы работаем только с комплектами и их согласованиями.
При настройке измерений в 1С следует обратить внимание на дополнительные свойства, которые влияют на поведение системы:
Свойство «Ведущее»
Если вы установите флаг Ведущее у измерения КомплектЧертежей, то при удалении карточки комплекта из справочника, все записи в регистре, связанные с этим комплектом, будут удалены автоматически. Это критически важно для поддержания ссылочной целостности базы данных.
Использование Реквизитов регистра
Помните, что помимо Измерений и Ресурсов в регистре есть Реквизиты. В чем разница?
Проанализируем код для корректного добавления новой записи в регистр, где все три поля являются измерениями:
НоваяЗапись = РегистрыСведений.СогласованияЧертежей.СоздатьМенеджерЗаписи();
НоваяЗапись.Объект = ВыбранныйОбъект;
НоваяЗапись.КомплектЧертежей = ВыбранныйКомплект;
НоваяЗапись.ПереченьСогласований = ТекущееСогласование;
// Устанавливаем ресурсы
НоваяЗапись.ДатаНачала = ТекущаяДата();
НоваяЗапись.ДатаОкончания = КонецДня(ТекущаяДата());
// Метод Записать(Истина) перезапишет ресурсы, если ключ совпадет.
// Метод Записать(Ложь) выдаст ошибку при совпадении ключа.
Попытка
НоваяЗапись.Записать(Ложь);
Исключение
Сообщить("Такое согласование для этого комплекта уже зарегистрировано!");
КонецПопытки;
Выясним причину ошибки: платформа 1С блокирует запись, если в регистре уже существует строка с идентичным набором Измерений. Резюмируем наши действия для решения проблемы:
Ведущее для основных разрезов учета, чтобы избежать появления «битых ссылок».