Почему при записи в независимый регистр сведений пропадают значения ресурсов и как это исправить?

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

При работе с независимыми регистрами сведений в 1С начинающие разработчики часто сталкиваются с неприятной ситуацией: при попытке программно изменить значение одного ресурса остальные ресурсы в той же записи внезапно «обнуляются» или очищаются. Рассмотрим, почему это происходит, проанализируем внутренние механизмы платформы и разберем правильные способы обновления данных.

Выясняем причину: механизм работы Набора Записей

Разберем ситуацию, описанную автором вопроса. Имеется регистр сведений ЗначенияСвойств с измерениями Номенклатура и Свойство, а также ресурсами Количество и КоличествоЗаявлено. При записи нового значения в ресурс Количество через объект НаборЗаписей, значение в КоличествоЗаявлено пропадает.

Основная причина кроется в логике работы метода Записать() объекта РегистрСведенийНаборЗаписей. По умолчанию этот метод выполняется с параметром Замещать = Истина. Это означает следующее:

  1. Система анализирует установленные фильтры в свойстве Отбор.
  2. При вызове метода Записать() 1С сначала полностью удаляет из базы данных все записи, которые соответствуют заданному отбору.
  3. Затем система берет те записи, которые в данный момент находятся в объекте НаборЗаписей в оперативной памяти, и записывает их в базу.

Если мы создали набор, установили отбор, но не вызвали метод Прочитать(), наш набор в памяти пуст. Когда мы добавляем в него одну новую строку и заполняем в ней только одно поле, остальные поля остаются пустыми (со значениями по умолчанию). В итоге старая полная запись удаляется, а новая «полупустая» записывается на её место. Именно поэтому ресурс КоличествоЗаявлено очищается.

Решение №1: Использование Набора Записей с предварительным чтением

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

Рассмотрим по шагам, как нужно действовать:

  1. Создаем объект НаборЗаписей.
  2. Устанавливаем фильтры по измерениям через свойство Отбор.
  3. Обязательно вызываем метод Прочитать().
  4. Модифицируем полученную коллекцию записей.
  5. Вызываем метод Записать().

Посмотрим на пример кода, который решает проблему:


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

// Читаем данные из базы в память
НаборЗаписей.Прочитать();

Если НаборЗаписей.Количество() > 0 Тогда
    // Если запись существует, редактируем её
    Запись = НаборЗаписей[0];
Иначе
    // Если записи нет, создаем новую
    Запись = НаборЗаписей.Добавить();
    Запись.Номенклатура = ТекущаяНоменклатура;
    Запись.Свойство = ТекущееСвойство;
КонецЕсли;

// Устанавливаем только нужный ресурс, остальные сохранятся
Запись.Количество = ТекущееКоличество;

НаборЗаписей.Записать();

В данном примере использование метода Количество() позволяет нам определить, была ли найдена существующая запись после выполнения Прочитать(). Если запись найдена, мы обращаемся к ней по индексу [0] и меняем только то, что нам нужно.

Решение №2: Использование Менеджера Записи

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

Проанализируем пример использования менеджера записи:


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

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

// Теперь в МенеджерЗаписи загружены все ресурсы из базы
// Если записи не было, поля будут пустыми (Выбран() вернет Ложь)
МенеджерЗаписи.Количество = ТекущееКоличество;

// Метод Записать() обновит существующую запись или создаст новую
МенеджерЗаписи.Записать();

Преимущества Менеджера Записи:

Что выбрать: Набор записей или Менеджер записи?

Выясним, в каких ситуациях какой объект будет предпочтительнее. Несмотря на удобство МенеджераЗаписи, у него есть свои ограничения.

Используйте Менеджер записи, если:

Используйте Набор записей, если:

Важные нюансы и блокировки данных

Разберем еще один критически важный момент — блокировки данных. При использовании НаборЗаписей.Записать() система накладывает блокировку на весь диапазон данных, попадающих в отбор. Если ваш отбор слишком «широкий» (например, только по одному измерению из пяти), вы можете заблокировать работу других пользователей с этим регистром.

При использовании МенеджерЗаписи блокировка всегда точечная — только на одну конкретную комбинацию измерений. Это делает работу приложения более стабильной в условиях высокой многопользовательской нагрузки.

Также стоит помнить о методе Записать(Ложь). Если передать Ложь в качестве параметра замещения, система попытается просто добавить запись. Но помните: если в независимом регистре уже есть запись с такими измерениями, вы получите ошибку нарушения уникальности. Для обновления ресурсов этот режим не подходит.

Подведем итог: Всегда используйте метод Прочитать() перед модификацией набора записей, если хотите сохранить данные в ресурсах, которые вы не планируете менять. Либо отдавайте предпочтение МенеджеруЗаписи для работы с одиночными строками.

← На главную