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