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