Как правильно добавить или изменить запись в периодическом независимом регистре сведений 1С?

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

Работа с регистрами сведений — одна из базовых и наиболее часто встречающихся задач при разработке в среде 1С. Однако использование независимых периодических регистров часто вызывает вопросы у начинающих разработчиков. Основные сложности обычно связаны с механизмом работы объекта РегистрСведенийНаборЗаписей, логикой установки отборов и пониманием того, как именно метод Записать() взаимодействует с уже существующими данными в базе.

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

Разбор типичных ошибок при работе с набором записей

Рассмотрим ситуацию, описанную в теме: разработчик пытается добавить запись в регистр, но сталкивается с тем, что либо Прочитать() возвращает пустой набор (хотя данные в базе есть), либо при выполнении Записать(Истина) все остальные записи в регистре удаляются. Проанализируем причины этих проблем.

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

2. Проблема "затирания" данных. Метод Записать(Истина) (или просто Записать(), так как Истина — значение по умолчанию) работает по следующему алгоритму:

  1. Система смотрит на установленные в объекте Отбор значения.
  2. В таблице базы данных удаляются все записи, которые соответствуют этому отбору.
  3. В базу записываются те строки, которые в данный момент находятся в коллекции набора в оперативной памяти.

Если вы создали новый набор записей и не установили в нем никакой отбор (или установили не по всем измерениям), вызов Записать(Истина) может привести к полной очистке регистра или удалению гораздо большего объема данных, чем вы планировали.

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

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


// Создаем объект набора записей
НаборЗаписей = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();

// Устанавливаем отбор по ключевым полям (Измерения + Период)
// Это гарантирует, что мы работаем только с конкретным срезом данных
НаборЗаписей.Отбор.ТранспортноеСредство.Установить(ТекущийОбъект.Ссылка);
НаборЗаписей.Отбор.Период.Установить(НачалоДня(ДатаЗначений));

// Создаем новую запись в наборе
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = НачалоДня(ДатаЗначений);
НоваяЗапись.ТранспортноеСредство = ТекущийОбъект.Ссылка;
НоваяЗапись.Характеристика = ВыбраннаяХарактеристика;
НоваяЗапись.Значение = 444;

// Записываем набор с замещением (Истина)
// Благодаря установленному отбору, система удалит только старую запись 
// с ТАКИМ ЖЕ ТС и ТАКИМ ЖЕ периодом, и запишет новую.
НаборЗаписей.Записать(Истина);

Важно помнить: значения полей, указанных в Отбор, должны в точности совпадать со значениями соответствующих полей в добавляемой записи НоваяЗапись. Если в отборе вы указали одну дату, а в самой записи — другую, система выдаст ошибку при попытке записи.

Использование метода Записать(Ложь)

Существует альтернативный подход — использование параметра Замещать = Ложь. В этом случае система не пытается предварительно удалить записи по отбору, а просто пытается добавить новые строки в таблицу.

Однако этот метод таит в себе опасность: если в базе уже есть запись с таким же набором измерений и периодом, возникнет исключение "Запись с такими ключевыми полями существует". Этот метод оправдан только при массовой загрузке заведомо новых данных, когда вы на 100% уверены в отсутствии дублей.

Альтернатива: Менеджер записи

Если вам нужно прочитать или изменить всего одну конкретную строку в независимом регистре, часто удобнее использовать МенеджерЗаписи. Это избавляет от необходимости работать с коллекциями (наборами) и позволяет обращаться к записи как к отдельному объекту.

Проанализируем пример работы с менеджером записи:


Менеджер = РегистрыСведений.МойРегистр.СоздатьМенеджерЗаписи();
Менеджер.ТранспортноеСредство = ТекущийОбъект.Ссылка;
Менеджер.Период = НачалоДня(ДатаЗначений);

// Пытаемся прочитать существующую запись из базы
Менеджер.Прочитать();

Если Менеджер.Выбран() Тогда
    // Запись найдена, можем обновить ресурсы
    Менеджер.Значение = 555;
Иначе
    // Записи нет, заполняем все поля для создания новой
    Менеджер.ТранспортноеСредство = ТекущийОбъект.Ссылка;
    Менеджер.Период = НачалоДня(ДатаЗначений);
    Менеджер.Характеристика = ВыбраннаяХарактеристика;
    Менеджер.Значение = 555;
КонецЕсли;

Менеджер.Записать();

Метод Записать() у менеджера записи автоматически определяет, нужно ли обновить существующую строку или создать новую, основываясь на значениях измерений и периода.

Технические нюансы и производительность

При выборе способа записи стоит учитывать еще несколько важных факторов:

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

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

← На главную