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