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