В процессе разработки на платформе 1С:Предприятие 8 часто возникает ситуация, когда при программной или интерактивной записи РегистрСведенийНаборЗаписей разработчик сталкивается с неожиданным поведением: события ПередЗаписью и ПриЗаписи срабатывают дважды (подобное поведение полезно учитывать, используя фреймворк для работы с подписками). Давайте разберемся, почему так происходит, и как правильно обрабатывать такие вызовы.
Важно понимать, что двойной вызов — это не ошибка платформы, а штатный механизм обеспечения транзакционной целостности данных. Когда вы изменяете запись в независимом регистре сведений, 1С выполняет две операции на уровне базы данных:
ПередЗаписью с «пустым» набором.ПередЗаписью, уже с заполненными данными.При первом вызове параметр Замещение равен Истина, так как платформа готовит «место» для новых данных, удаляя старые. Во втором случае происходит уже непосредственная фиксация ваших данных. Поскольку объект НаборЗаписей в рамках одной транзакции один и тот же, мы можем воспользоваться этим для управления логикой событий.
Чтобы избежать выполнения тяжелых проверок (например, если используется программное создание СКД) или повторного проведения бизнес-логики при каждом вызове, мы можем реализовать «межсобытийную память». Для этого идеально подходит свойство ДополнительныеСвойства объекта НаборЗаписей.
Рассмотрим по шагам, как реализовать универсальный механизм отслеживания:
В событии ПередЗаписью мы проверяем текущее состояние набора. Если набор пуст (нет записей) и при этом модифицированность не установлена явно, мы можем пометить этот этап специальным флагом в ДополнительныеСвойства.
Процедура ПередЗаписью(Отказ, Замещение)
// Проверяем, является ли текущая операция удалением (очисткой)
Если ЭтотОбъект.Количество() = 0 И ЭтотОбъект.Модифицированность = Ложь Тогда
ЭтотОбъект.ДополнительныеСвойства.Вставить("clear", Истина);
КонецЕсли;
КонецПроцедуры
Теперь, когда мы пометили первый этап (удаление), мы можем безопасно проверить наличие этой пометки в событии ПриЗаписи или в последующих обработчиках. Это позволит нам выполнить нужный код только один раз или в зависимости от конкретного этапа операции.
Процедура ПриЗаписи(Отказ, Замещение)
Если ЭтотОбъект.ДополнительныеСвойства.Свойство("clear") Тогда
// Здесь выполняется логика для этапа удаления
// Например: очистка связанных данных, логирование и т.д.
Возврат;
КонецЕсли;
// Здесь выполняется основная логика для этапа записи новых данных
// Проверки валидности, расчеты и т.д.
КонецПроцедуры
Рассмотрим преимущества такого подхода:
МенеджерЗаписи.ДополнительныеСвойства (например, идентификаторы пользователей или флаги внешних условий), чтобы точно знать, какой именно код сейчас выполняется.Мы рекомендуем всегда придерживаться этого паттерна, если ваша логика в модуле набора записей критична к количеству вызовов или зависит от состояния данных «до» и «после» записи. Такой подход делает код предсказуемым и значительно облегчает отладку сложных транзакционных операций в 1С:ERP и других конфигурациях.