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