Почему не удаляется запись регистра сведений при удалении значения ведущего измерения?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие мы часто сталкиваемся с задачами по очистке данных. Казалось бы, механизмы платформы отлажены годами: если мы используем независимый регистр сведений и устанавливаем для измерения флаг «Ведущее», мы ожидаем, что платформа сама позаботится о целостности данных. Логика проста: удаляем элемент справочника — автоматически удаляются все записи регистра, где этот элемент выступал в роли ведущего измерения. При необходимости полностью очистить базу от данных конкретной фирмы в типовых конфигурациях применяется обработка для рекурсивного выборочного удаления организаций.

Однако иногда возникает ситуация, когда этот механизм дает сбой. Вы удаляете объект, а запись в регистре остается, но вместо красивого названия элемента вы видите пугающую надпись <Объект не найден...>. Давайте подробно разберем, почему так происходит, какие скрытые механизмы платформы на это влияют и как правильно выполнять программное удаление данных.

Механизм работы Ведущего измерения

Для начала давайте вспомним теорию. В независимых регистрах сведений свойство измерения Ведущее (Master) играет критическую роль в поддержании ссылочной целостности базы данных.

Когда вы устанавливаете этот флаг, вы сообщаете платформе следующее:

  1. Существование записи этого регистра не имеет смысла без существования объекта, указанного в этом измерении.
  2. Жизненный цикл записи регистра жестко привязан к жизненному циклу объекта-измерения.

В штатном режиме работы, когда пользователь или программный код удаляет элемент справочника (или документ), платформа автоматически инициирует транзакцию, в которой ищет все записи регистров, где этот объект является ведущим измерением, и удаляет их. Это называется каскадным удалением.

Также стоит отметить важный нюанс, который мы выяснили в ходе анализа: если в регистре сведений несколько ведущих измерений, то работает логика «ИЛИ». Удаление значения любого из ведущих измерений влечет за собой удаление всей записи регистра.

Диагностика проблемы: почему остаются битые ссылки?

Вернемся к нашей проблеме. Мы выполняем удаление объекта, но каскадное удаление не срабатывает. В регистре остается запись, хранящая уникальный идентификатор (GUID) удаленного объекта, которому в базе данных уже ничего не соответствует. Визуально это отображается как <Объект не найден>.

Если мы исключим очевидные ошибки (например, забыли поставить флаг «Ведущее» в конфигураторе), то наиболее вероятная причина кроется в режиме выполнения кода удаления.

Разберем свойство ОбменДанными.Загрузка.

У любого ссылочного объекта (СправочникОбъект, ДокументОбъект и т.д.) есть свойство ОбменДанными, у которого, в свою очередь, есть булево свойство Загрузка.


// Пример кода, который приводит к ошибке
Объект = СсылкаНаНоменклатуру.ПолучитьОбъект();
Объект.ОбменДанными.Загрузка = Истина; 
Объект.Удалить();

Давайте проанализируем, что делает платформа, когда видит ОбменДанными.Загрузка = Истина:

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

Установка этого свойства в Истина при удалении говорит системе: «Просто физически удали эту запись из таблицы справочника, не трать время на поиск связей». Именно поэтому запись из справочника исчезает, а связанная запись в регистре сведений остается нетронутой, превращаясь в «битую ссылку».

Как правильно удалять объекты?

Если ваша задача — удалить объект так, чтобы сработали все механизмы платформы, включая очистку ведущих измерений, вы не должны включать режим загрузки данных.

Правильный код для программного удаления выглядит так:


Попытка
    Объект = СсылкаНаУдаление.ПолучитьОбъект();
    
    // Явно указываем Ложь (по умолчанию оно и так Ложь, но для наглядности)
    // или просто не трогаем это свойство.
    Объект.ОбменДанными.Загрузка = Ложь; 
    
    Объект.Удалить();
Исключение
    // Обработка ошибки, если удалить нельзя (например, есть ссылки не в ведущих измерениях)
    Сообщить("Не удалось удалить объект: " + ОписаниеОшибки());
КонецПопытки;

При выполнении метода Удалить() без флага загрузки, платформа:

  1. Начнет транзакцию.
  2. Найдет все записи независимых регистров сведений, где этот объект указан в ведущем измерении.
  3. Удалит эти записи.
  4. Удалит сам объект.
  5. Зафиксирует транзакцию.

Если в процессе удаления записей регистра произойдет ошибка (например, сработает запрет в подписке на событие регистра), то отменится и удаление основного объекта.

Что делать, если проблема уже возникла?

Если вы обнаружили в базе записи с <Объект не найден> в ведущих измерениях, это свидетельствует о нарушении ссылочной целостности (логической целостности данных). Такое часто случается после некорректно написанных обработок очистки данных или загрузок обменов. Для комплексного выявления таких записей во всей информационной базе подойдёт обработка для поиска битых ссылок «Объект не найден».

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

  1. Запустите режим Конфигуратор.
  2. Перейдите в меню Администрирование -> Тестирование и исправление.
  3. Выберите пункты:
    • Проверка логической целостности.
    • Проверка ссылочной целостности.
  4. В настройках (ниже списка проверок) для пункта «При наличии ссылок на несуществующие объекты» выберите вариант действий. Для регистров сведений логичнее всего выбрать «Очищать ссылки» или «Удалять объект» (в контексте записи регистра это приведет к удалению строки).

Будьте осторожны с тестированием и исправлением на рабочих базах, обязательно делайте резервную копию перед запуском. В качестве альтернативы полному тестированию базы для точечной очистки или корректировки данных можно использовать универсальную обработку регистров сведений для удаления и замены записей по фильтрам.

Резюме

Подведем итог нашему расследованию:

← На главную