К статье
Практический материал

Разработка и Конфигурация · 10 мин

Чем отличается ПередЗаписью от ПриЗаписи в 1С

Разбираем различия событий ПередЗаписью и ПриЗаписи в 1С: порядок вызова, транзакции, типичные задачи, примеры кода и частые ошибки разработчика.

События ПередЗаписью и ПриЗаписи — два самых часто используемых обработчика при работе с объектами в 1С:Предприятие 8. Оба срабатывают в процессе записи элемента справочника, документа или другого объекта, но вызываются на разных этапах и предназначены для разных задач. Непонимание разницы приводит к типичным ошибкам: рекурсивным записям, потере данных, нарушению целостности базы.

Главное различие — момент вызова относительно транзакции записи и возможность отменить запись. ПередЗаписью выполняется до начала физической записи в базу данных и позволяет отказаться от сохранения. ПриЗаписи вызывается уже внутри транзакции, когда объект фактически записывается, и отменить запись через параметр Отказ в нём нельзя — только вызвать исключение.

Порядок вызова событий при записи объекта

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

Важно понимать, что между ПередЗаписью и ПриЗаписи проходит граница транзакции. Всё, что сделано в ПередЗаписью, ещё не попало в базу; всё, что выполняется в ПриЗаписи, уже происходит внутри транзакции и будет откачено вместе с записью объекта, если возникнет исключение.

Что делает событие ПередЗаписью

Обработчик ПередЗаписью вызывается до начала транзакции. Его ключевая особенность — параметр Отказ: если установить Отказ = Истина, запись не будет выполнена, транзакция не начнётся, а пользователь получит сообщение об ошибке. Это делает событие основным местом для проверки корректности данных.

Типичные задачи для ПередЗаписью: валидация заполнения реквизитов, проверка уникальности по бизнес-правилам, автоматическое заполнение служебных полей (например, автора изменения или даты последней модификации), запрет записи по условиям доступа. Также здесь удобно сравнивать новые значения со старыми, читая текущие данные объекта из базы через запрос или метод ПолучитьОбъект() по ссылке.

Процедура ПередЗаписью(Отказ)

Если Не ЗначениеЗаполнено(ИНН) Тогда

ОбщегоНазначения.СообщитьПользователю(

"Не заполнен ИНН контрагента", , , , Отказ);

КонецЕсли;

КонецПроцедуры

Что делает событие ПриЗаписи

Обработчик ПриЗаписи вызывается внутри транзакции записи. Параметр Отказ в нём формально присутствует, но установка его в Истина не отменяет запись штатно — для отмены нужно вызывать исключение через ВызватьИсключение, что приведёт к откату всей транзакции.

Основное назначение ПриЗаписи — действия, которые должны выполняться атомарно с записью объекта: регистрация изменений в планах обмена, запись связанных объектов, обновление регистров сведений, фиксация истории изменений. Если такая связанная операция завершится ошибкой, откатится и сама запись объекта — целостность данных сохранится.

Сравнение ключевых характеристик событий

КритерийПередЗаписьюПриЗаписи
Момент вызоваДо начала транзакцииВнутри транзакции записи
Отмена записиЧерез Отказ = ИстинаТолько через исключение
Данные в базеОбъект ещё не записанЗапись выполняется в транзакции
Типичные задачиПроверки, валидация, заполнение реквизитовСвязанные записи, регистрация изменений
Риск при ошибкеЗапись просто не состоитсяОткат всей транзакции

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

Где размещать логику

ПередЗаписью

Подходит для проверок и заполнения реквизитов самого объекта. Ограничение: запись связанных объектов здесь небезопасна — при отказе они уже будут изменены.

ПриЗаписи

Подходит для записи связанных данных и регистрации в обменах. Ограничение: нельзя штатно отменить запись, а длительные операции удерживают транзакцию и блокировки.

Типичные ошибки при использовании обработчиков

Самая распространённая ошибка — попытка отменить запись в ПриЗаписи через Отказ = Истина и ожидание, что объект не сохранится. Платформа проигнорирует этот параметр, запись завершится, а логика проверки окажется бесполезной. Проверки, которые должны блокировать сохранение, нужно переносить в ПередЗаписью или в ОбработкаПроверкиЗаполнения.

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

Третья ошибка — выполнение тяжёлых запросов и длительных операций в ПриЗаписи. Пока транзакция открыта, платформа удерживает блокировки записанных данных, и другие пользователи ждут. В многопользовательской базе это приводит к конфликтам блокировок и тайм-аутам.

Типичные ошибки
01
Установка Отказ = Истина в ПриЗаписи — запись всё равно выполнится, проверка не сработает
02
Запись связанных объектов в ПередЗаписью — при отказе от основной записи в базе остаются «осиротевшие» данные
03
Вызов Записать() для того же объекта внутри его обработчиков — рекурсия и переполнение стека
04
Длительные вычисления в ПриЗаписи — удержание транзакции и блокировок, конфликты у пользователей

Практические рекомендации по выбору обработчика

Выбирайте обработчик по принципу: «проверяем и готовим — до, изменяем базу — внутри». Для валидации есть ещё более специализированное событие ОбработкаПроверкиЗаполнения, которое вызывается перед ПередЗаписью и предназначено именно для проверки заполнения реквизитов — используйте его в первую очередь.

Если нужно сравнить старые и новые значения реквизитов, делайте это в ПередЗаписью: прочитайте текущую версию объекта из базы по ссылке и сравните. В ПриЗаписи старые данные уже перезаписаны, и получить их сложнее.

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

Как организовать контроль записи
  1. 1
    Определите, что нужно: проверить данные или выполнить связанные действия в базе
  2. 2
    Проверки заполнения разместите в ОбработкаПроверкиЗаполнения или ПередЗаписью с установкой Отказ
  3. 3
    Старые значения реквизитов при необходимости сохраните в ДополнительныеСвойства в ПередЗаписью
  4. 4
    Запись связанных объектов и регистров выполните в ПриЗаписи, защитившись от рекурсии флагом в ДополнительныеСвойства
  5. 5
    Протестируйте сценарии: успешная запись, отказ по проверке, ошибка в связанной записи — во всех случаях база должна остаться консистентной

Как проверить, что логика работает правильно

После внедрения обработчиков проверьте три сценария. Первый — штатная запись: объект сохраняется, связанные данные создаются корректно. Второй — отказ в ПередЗаписью: объект не записан, связанных данных в базе нет. Третий — исключение в ПриЗаписи: откатывается и основной объект, и связанные записи.

Дополнительно проверьте поведение при групповой записи и в обменах данными: обработчики срабатывают и при программной записи, поэтому логика не должна зависеть от интерактивного контекста (например, от наличия открытой формы или текущего пользователя-интерактивщика).

Контрольные точки

Как проверить результат

Отказ в ПередЗаписью
Норма

Объект не записан, связанных данных нет

Тревожный признак

Объект не записан, но связанные объекты созданы

Исключение в ПриЗаписи
Норма

Откачены и объект, и связанные записи

Тревожный признак

Объект записан, а связанные данные отсутствуют

Повторная запись того же объекта
Норма

Обработчики отрабатывают один раз, без рекурсии

Тревожный признак

Ошибка переполнения стека или многократные вызовы

FAQ

Можно ли в ПередЗаписью прочитать старые значения реквизитов объекта?

Да. Объект в этот момент ещё не записан, поэтому по его ссылке можно выполнить запрос к базе или получить объект через Ссылка.ПолучитьОбъект() и сравнить значения. Для новых объектов ссылка ещё не существует в базе — проверяйте ЭтоНовый().

Почему Отказ = Истина в ПриЗаписи не отменяет запись?

К моменту вызова ПриЗаписи транзакция уже начата, и платформа не обрабатывает параметр Отказ в этом событии. Отменить запись можно только вызвав исключение через ВызватьИсключение — тогда вся транзакция откатится.

Чем ПриЗаписи отличается от ПослеЗаписи?

ПриЗаписи выполняется внутри транзакции в модуле объекта, ПослеЗаписи — после фиксации транзакции и существует только в модуле формы. Для связанных с базой действий используйте ПриЗаписи, для обновления интерфейса — ПослеЗаписи.

Где лучше проверять заполнение реквизитов?

Оптимально — в событии ОбработкаПроверкиЗаполнения: оно вызывается до ПередЗаписью, поддерживает отказ и собирает все ошибки заполнения в одно сообщение. ПередЗаписью оставьте для проверок, требующих дополнительной логики за пределами простой заполненности.

Как защититься от рекурсии при записи связанных объектов?

Используйте флаг в ДополнительныеСвойства: перед записью связанного объекта установите, например, ДополнительныеСвойства.Вставить("НеРегистрироватьСвязь", Истина), а в начале обработчика проверяйте наличие этого флага и завершайте выполнение.

Срабатывают ли эти события при обмене данными?

Да, обработчики вызываются при любой записи, включая загрузку через обмены. Если логика не должна выполняться при обмене, проверяйте свойство ОбменДанными.Загрузка — при значении Истина обработчики обычно пропускают, но стандартные проверки платформы тогда тоже не выполняются.

Итог

Что важно запомнить

ПередЗаписью — до транзакции, для проверок и заполнения, отмена через Отказ. ПриЗаписи — внутри транзакции, для связанных записей, отмена только через исключение. Проверяйте в первом, изменяйте базу во втором, защищайтесь от рекурсии через ДополнительныеСвойства.