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

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

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

Техническая причина двойного вызова

Важно понимать, что двойной вызов — это не ошибка платформы, а штатный механизм обеспечения транзакционной целостности данных. Когда вы изменяете запись в независимом регистре сведений, 1С выполняет две операции на уровне базы данных:

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

При первом вызове параметр Замещение равен Истина, так как платформа готовит «место» для новых данных, удаляя старые. Во втором случае происходит уже непосредственная фиксация ваших данных. Поскольку объект НаборЗаписей в рамках одной транзакции один и тот же, мы можем воспользоваться этим для управления логикой событий.

Решение проблемы с помощью ДополнительныхСвойств

Чтобы избежать выполнения тяжелых проверок (например, если используется программное создание СКД) или повторного проведения бизнес-логики при каждом вызове, мы можем реализовать «межсобытийную память». Для этого идеально подходит свойство ДополнительныеСвойства объекта НаборЗаписей.

Рассмотрим по шагам, как реализовать универсальный механизм отслеживания:

Шаг 1: Идентификация первого вызова (удаление)

В событии ПередЗаписью мы проверяем текущее состояние набора. Если набор пуст (нет записей) и при этом модифицированность не установлена явно, мы можем пометить этот этап специальным флагом в ДополнительныеСвойства.


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

Шаг 2: Условное выполнение логики в ПриЗаписи

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


Процедура ПриЗаписи(Отказ, Замещение)
    Если ЭтотОбъект.ДополнительныеСвойства.Свойство("clear") Тогда
        // Здесь выполняется логика для этапа удаления
        // Например: очистка связанных данных, логирование и т.д.
        Возврат;
    КонецЕсли;

    // Здесь выполняется основная логика для этапа записи новых данных
    // Проверки валидности, расчеты и т.д.
КонецПроцедуры

Почему это лучший способ?

Рассмотрим преимущества такого подхода:

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

← На главную