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