В процессе разработки и тестирования конфигураций на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда непосредственное удаление элемента справочника (через Shift+Del в интерфейсе или программно методом Удалить()) ведет к разным последствиям. В одной базе удаляется только сам объект, оставляя «битые ссылки» в связанных данных, а в другой — вместе с владельцем бесследно исчезают записи в регистрах и даже элементы подчиненных справочников. Разберем подробно, почему так происходит, и какие механизмы платформы за это отвечают.
Для начала проанализируем, чем отличается непосредственное удаление от стандартного процесса пометки на удаление. Когда мы используем интерактивную пометку, платформа лишь устанавливает признак ПометкаУдаления = Истина. Сами данные остаются в базе, и система контроля ссылочной целостности позволяет позже найти все упоминания этого объекта через стандартную обработку «Удаление помеченных объектов».
Однако при вызове метода Объект.Удалить() или нажатии Shift+Del (если это разрешено правами доступа), происходит жесткое удаление записи из таблицы СУБД. В этом режиме платформа по умолчанию не проверяет наличие ссылок на этот объект в других местах. Рассмотрим типичный пример программного удаления:
// Пример непосредственного удаления объекта без проверок
СсылкаНаНоменклатуру = Справочники.Номенклатура.НайтиПоКоду("00001");
ОбъектНоменклатура = СсылкаНаНоменклатуру.ПолучитьОбъект();
Если ОбъектНоменклатура <> Неопределено Тогда
ОбъектНоменклатура.Удалить(); // Объект исчезает из базы мгновенно
КонецЕсли;
После выполнения этого кода во всех документах и регистрах, где использовалась данная номенклатура, появится надпись "Объект не найден". Но почему же в некоторых случаях связанные данные удаляются вместе с ним? Выясним основную причину.
Наиболее распространенная причина «магического» исчезновения данных — использование свойства метаданных «Ведущее». Это свойство доступно для измерений регистров сведений. Рассмотрим подробнее, как оно работает.
Если в регистре сведений (например, «Штрихкоды» или «ЦеныНоменклатуры») для измерения «Номенклатура» установлен флаг Ведущее, это сообщает платформе, что запись регистра не имеет смысла без этого объекта. Платформа берет на себя обязанность соблюдать чистоту данных: при физическом удалении владельца (Номенклатуры) она автоматически генерирует SQL-запросы на удаление всех записей регистра, где в данном измерении указана эта ссылка.
Почему это важно:
Если вы наблюдаете, что в одной базе регистры очищаются, а в другой — нет, в первую очередь сравните настройки измерений в конфигураторе. Проверьте свойство Ведущее для ключевых полей.
Ситуация со справочниками (например, «ЕдиницыИзмерения», владельцем которых является «Номенклатура») сложнее. В классической десктопной платформе 1С нет встроенного свойства, аналогичного «Ведущему», которое бы автоматически удаляло подчиненный справочник при физическом удалении владельца через Объект.Удалить().
Если в вашей базе вместе с номенклатурой удаляются ее единицы измерения, проанализируем следующие скрытые факторы:
1. Подписки на события. Даже если вы уверены, что кода нет, проверьте подписки на событие ПередУдалением или ПриУдалении. Обратите внимание на «универсальные» подписки, где в качестве источника указан не конкретный справочник, а общий тип, например, СправочникОбъект. Поиск ссылок на объект в конфигураторе может их не показать, если они настроены широко.
2. Расширения конфигурации. Если база не является абсолютно «чистой» самопиской, в ней могут быть установлены расширения. Проверьте наличие кода в модулях объектов или подписках внутри расширений. Они могут перехватывать удаление и программно очищать подчиненные связи.
3. Мобильная платформа. Как было замечено в обсуждении, использование мобильной платформы накладывает свои особенности. Мобильная платформа использует базу данных SQLite. В ней механизмы каскадного удаления и синхронизации данных могут работать специфично, особенно если настроен автоматический обмен данными. При удалении объекта система может инициировать цепочку удалений для синхронизации состояния с основным узлом.
Если визуальный осмотр метаданных не дает ответа, а «чудеса» продолжаются, воспользуемся инструментами глубокого анализа. Настроим Технологический журнал (ТЖ). Это позволит нам увидеть, какие именно команды уходят в СУБД в момент нажатия Shift+Del.
Нам интересны события DBMSSQL (для MS SQL) или аналогичные для других СУБД. В логах мы увидим последовательность:
DELETE FROM _ReferenceX (Удаление самой номенклатуры).DELETE FROM _ReferenceY (где Y — таблица подчиненного справочника), значит, команду дает либо ядро платформы, либо скрытый триггер в базе (что для 1С редкость).Если же мы видим между этими командами вызовы других процедур (события CALL), значит, какой-то программный код все же выполняется.
Разберем, как правильно организовать удаление, чтобы избежать «битых ссылок» или, наоборот, не потерять данные случайно:
Безопасное удаление: Для удаления объектов всегда рекомендуется использовать стандартный механизм контроля ссылок. Программно это выглядит так:
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(СсылкаНаОбъект);
// Проверяем, можно ли удалять
ТаблицаСсылок = НайтиПомеченноеНаУдаление(МассивСсылок);
Если ТаблицаСсылок.Количество() = 0 Тогда
Объект = СсылкаНаОбъект.ПолучитьОбъект();
Объект.Удалить();
Иначе
Сообщить("Объект используется в других местах, удаление невозможно!");
КонецЕсли;
Использование критериев отбора: Иногда разработчики реализуют собственное каскадное удаление. Рассмотрим пример, который можно разместить в модуле объекта владельца:
Процедура ПередУдалением(Отказ)
// Очищаем подчиненный справочник вручную
Выборка = Справочники.ЕдиницыИзмерения.Выбрать(, ЭтотОбъект.Ссылка);
Пока Выборка.Следующий() Цикл
ОбъектЕдиница = Выборка.ПолучитьОбъект();
ОбъектЕдиница.Удалить();
КонецЦикла;
КонецПроцедуры
Проверьте наличие подобного кода в модулях ваших справочников. Именно он чаще всего является причиной удаления подчиненных объектов в «самописках», создавая иллюзию автоматического поведения платформы.
Подводя итог: если у вас удаляются регистры — проверьте свойство «Ведущее». Если удаляются справочники — ищите скрытый код в подписках, расширениях или модулях объектов, так как штатно платформа 1С не удаляет подчиненные справочники каскадно при непосредственном удалении владельца.