Как отменить изменения в объекте документа 1С (ДокументОбъект), внесенные в памяти, если они не были записаны в базу данных?

Программист 1С v8.3 (Обычные формы)
← На главную

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

Понимание работы с ДокументОбъект в 1С

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

  1. Получение объекта: Вызов метода ДокСсылка.ПолучитьОбъект() создает в оперативной памяти вашего компьютера (на клиенте или на сервере, в зависимости от контекста выполнения) новый экземпляр объекта типа ДокументОбъект. Этот экземпляр является точной копией текущего состояния документа из базы данных на момент вызова.
  2. Внесение изменений в память: Все последующие модификации, которые мы производим с переменной ДокОбъект (изменение реквизитов, эффективная работа с табличными частями документов в оперативной памяти), происходят исключительно с этой копией. Эти изменения не затрагивают данные, хранящиеся в базе данных, до тех пор, пока мы явно не дадим команду на сохранение.
  3. Изолированность изменений: Важно понимать, что работа с ДокументОбъект в памяти аналогична редактированию текстового файла в редакторе: вы можете вносить любые изменения, но они станут постоянными только после нажатия кнопки "Сохранить". Без этого действия все изменения будут потеряны при закрытии редактора.

В нашем случае, когда мы говорим об "обычных формах" и работе на клиенте, все эти манипуляции происходят в адресном пространстве клиентского приложения, и серверная база данных о них ничего не знает.

Ключевая роль метода Записать() и транзакций

Центральным моментом в сохранении изменений из оперативной памяти в базу данных является метод Записать() объекта ДокументОбъект. Давайте проанализируем его значение:

  1. Команда на сохранение: Только вызов ДокОбъект.Записать() (или ДокОбъект.Записать(РежимЗаписиДокумента.Проведение), ДокОбъект.Записать(РежимЗаписиДокумента.Запись) и т.д.) инициирует процесс передачи внесенных в память изменений в базу данных. Без этой команды никаких попыток записи не происходит.
  2. Механизм транзакций: Платформа 1С использует транзакции и блокировки для обеспечения целостности данных. Транзакция — это неделимая последовательность операций, которая либо выполняется целиком (все изменения фиксируются), либо полностью откатывается (все изменения отменяются).
    • Когда мы вызываем Записать(), 1С открывает новую транзакцию или присоединяется к уже существующей. Все изменения, которые должны быть сохранены этим вызовом, включаются в эту транзакцию.
    • Если в процессе записи возникает ошибка, вся транзакция откатывается, и база данных возвращается к состоянию, которое было до начала транзакции.
    • Если метод Записать() не был вызван вообще, то для сохранения изменений в базе данных никакая транзакция не открывалась и не была зафиксирована. Соответственно, никаких изменений в базу данных не попадает.
  3. Отсутствие блокировок: До вызова Записать() документ в базе данных не блокируется для других пользователей (если только мы не инициировали блокировку вручную или в рамках другой операции). Это означает, что другие пользователи могут продолжать работать с тем же документом, и их изменения не будут пересекаться с нашими незаписанными изменениями в памяти.

Таким образом, наша "движуха" с ДокОбъект полностью изолирована и невидима для базы данных до момента явной команды на запись.

Жизненный цикл переменных и сборщик мусора

Теперь давайте разберем, что происходит с переменной ДокОбъект и связанным с ней объектом в памяти при выходе из процедуры:

  1. Область видимости переменной: Переменная ДокОбъект, созданная внутри процедуры (как в нашем примере), является локальной переменной. Это означает, что она существует только в течение выполнения данной процедуры. Как только выполнение процедуры завершается, все локальные переменные этой процедуры автоматически выходят из области видимости.
  2. "Смерть" переменной: Когда переменная выходит из области видимости, она перестает существовать, и ссылка, которую она содержала на объект ДокументОбъект в памяти, исчезает.
  3. Работа сборщика мусора: Платформа 1С осуществляет автоматическое управление жизненным циклом переменных и объектов в 1С 8.3 через механизм сборки мусора (Garbage Collector).
    • Когда объект в памяти (в нашем случае, экземпляр ДокументОбъект со всеми незаписанными изменениями) больше не имеет активных ссылок, указывающих на него, он становится "недостижимым".
    • Сборщик мусора периодически сканирует память и выявляет такие недостижимые объекты. Обнаружив их, он автоматически освобождает занимаемую ими память, делая ее доступной для использования другими частями программы.
    • В вашем сценарии, когда вы просто выходите из процедуры, переменная ДокОбъект "умирает", и объект в памяти, на который она ссылалась, становится кандидатом на удаление сборщиком мусора. Это происходит автоматически, без нашего участия.
  4. Необходимость явного обнуления (ДокОбъект = Неопределено;): Некоторые программисты предпочитают явно обнулять переменные, присваивая им значение Неопределено, считая это "хорошим тоном" для освобождения памяти. В большинстве простых случаев, таких как ваш, это избыточно. Сборщик мусора 1С достаточно эффективно справляется со своей задачей. Однако, в более сложных сценариях (например, с очень большими объектами, или при длительных фоновых процессах, где память критична, или в случае возникновения циклических ссылок), явное обнуление может помочь сборщику мусора быстрее идентифицировать и освободить память, но это скорее оптимизация, чем обязательное требование для корректной работы. В вашем случае это абсолютно не требуется.

Итоговое подтверждение и вывод

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

  1. Да, вам не нужно как-то специально "закрывать" ДокОбъект или выполнять какие-либо другие действия для отмены изменений.
  2. Достаточно просто выйти из процедуры.
  3. При этом переменная ДокОбъект умрет (выдет из области видимости), а объект в памяти, на который она ссылалась, будет утилизирован сборщиком мусора.
  4. Документ в базе данных останется без изменений в своем первоначальном виде, поскольку метод Записать() не был вызван, и никакая транзакция по сохранению изменений не была зафиксирована.

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

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

← На главную