При настройке правил обмена в конфигурации «Конвертация данных 2» (КД 2) разработчики иногда допускают критическую ошибку — забывают сопоставить стандартный реквизит ЭтоГруппа для иерархических справочников. В результате первой загрузки папки из базы-источника создаются в базе-приемнике как обычные элементы.
Попытка исправить правила обмена (поставив галочку поиска по полю ЭтоГруппа) и повторно запустить выгрузку/загрузку не приносит результата: объекты так и остаются элементами. В этой статье мы подробно разберем, почему так происходит, проанализируем внутренние механизмы платформы «1С:Предприятие» и рассмотрим три эффективных способа решения этой проблемы без потери ссылочной целостности базы данных.
Для того чтобы понять, почему обновленные правила обмена игнорируют признак группы при повторной загрузке, обратимся к объектной модели платформы 1С. Свойство ЭтоГруппа (в англоязычном варианте IsFolder) для объектов справочников имеет статус «Только чтение».
При чтении XML-файла позиционирование и создание объектов происходит по следующему алгоритму:
ЭтоГруппа. Если оно равно Истина, вызывается метод СоздатьГруппу(), если Ложь — метод СоздатьЭлемент().ЭтоГруппа игнорируется платформой на уровне ядра, так как у существующего объекта класса СправочникОбъект изменить этот признак напрямую невозможно. Программа не выдает ошибку, но тихо пропускает это поле, оставляя объект элементом.Таким образом, просто «накатить» правильные правила поверх ошибочно загруженных данных не получится. Нам придется применить специальные технические приемы.
Рассмотрим подробнее три основных сценария решения этой проблемы.
---
Этот способ подходит как для файловых, так и для клиент-серверных информационных баз. Суть метода заключается в том, что мы временно удаляем ошибочный элемент и тут же создаем на его месте группу с точно таким же Уникальным Идентификатором (GUID). Благодаря сохранению GUID все существующие ссылки в документах, регистрах и других справочниках не «слетят» и продолжат корректно указывать на созданную группу.
Проанализируем алгоритм работы специальной обработки, которую необходимо написать:
Код, Наименование, Родитель и сам УникальныйИдентификатор.Удалить().Ниже представлен пример программного кода для реализации этого сценария. Этот код можно использовать во внешней обработке:
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
// Определяем условие, по которому объект должен стать группой
// Например, мы передали список ГУИДов или сверяем по какому-то признаку
Если НеобходимаКонвертацияВГруппу(Выборка.Ссылка) Тогда
СсылкаНаОбъект = Выборка.Ссылка;
СтарыйGUID = СсылкаНаОбъект.УникальныйИдентификатор();
// Сохраняем значения ключевых реквизитов
СтруктураСвойств = Новый Структура;
СтруктураСвойств.Вставить("Код", Выборка.Код);
СтруктураСвойств.Вставить("Наименование", Выборка.Наименование);
СтруктураСвойств.Вставить("Родитель", Выборка.Родитель);
// 1. Физически удаляем ошибочный элемент из базы данных.
// Используем ОбменДанными.Загрузка = Истина, чтобы обойти проверки ссылочной целостности
ОбъектЭлемента = СсылкаНаОбъект.ПолучитьОбъект();
ОбъектЭлемента.ОбменДанными.Загрузка = Истина;
Попытка
ОбъектЭлемента.Удалить();
Исключение
ЗаписьЖурналаРегистрации("Конвертация", УровеньЖурналаРегистрации.Ошибка,,,
"Не удалось удалить элемент: " + ОписаниеОшибки());
Продолжить;
КонецПопытки;
// 2. Создаем группу с точно таким же уникальным идентификатором
НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылку(СтарыйGUID);
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
НоваяГруппа.УстановитьСсылкуНового(НоваяСсылка);
// Заполняем свойства
ЗаполнитьЗначенияСвойств(НоваяГруппа, СтруктураСвойств);
// Записываем группу в режиме обмена данными
НоваяГруппа.ОбменДанными.Загрузка = Истина;
Попытка
НоваяГруппа.Записать();
Исключение
ЗаписьЖурналаРегистрации("Конвертация", УровеньЖурналаРегистрации.Ошибка,,,
"Не удалось записать новую группу: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Важное примечание: Использование свойства ОбменДанными.Загрузка = Истина является критически важным. Без этого флага платформа заблокирует удаление элемента, если на него уже ссылаются другие объекты (например, проведенные документы), и выбросит исключение.
---
Если ваша база данных работает под управлением MS SQL Server, PostgreSQL или другой СУБД, у вас есть возможность исправить признак ЭтоГруппа мгновенно для любого количества объектов, избежав долгого процесса удаления и создания. Это самый быстрый и безопасный способ с точки зрения сохранения целостности транзакций.
На уровне таблиц СУБД признак группы хранится в бинарном виде в специальной колонке. Разберем логику хранения:
_ReferenceXXXX (где XXXX — внутренний числовой идентификатор таблицы)._Folder._Folder записано значение 0 (или 0x00).1 (или 0x01).Для исправления ситуации нам достаточно изменить значение в колонке _Folder с 0 на 1 для списка нужных идентификаторов объектов. Схематично SQL-запрос обновления выглядит следующим образом:
-- ПРИМЕР ДЛЯ MS SQL SERVER
-- Предварительно необходимо перевести ГУИДы 1С в бинарный формат SQL (с учетом перестановки байт)
UPDATE _Reference123
SET _Folder = 0x01
WHERE _IDRRef IN (0x80E800155D050B0111E29BCF2E3A0B66, 0x80E800155D050B0111E29BCF2E3A0B67);
ВНИМАНИЕ! КРАТЧАЙШИЙ ПУТЬ К ПОВРЕЖДЕНИЮ БАЗЫ ДАННЫХ: Прямая запись в СУБД обходит бизнес-логику платформы «1С:Предприятие». После выполнения подобного запроса обязательно выполните следующие действия:
---
Если обмен данными производился в пустую базу-приемник или в базу, где пользователи еще не успели создать новые документы и связать их с ошибочно загруженными элементами, самым простым и чистым решением будет полное удаление некорректно созданных объектов.
Выполните следующие шаги:
ЭтоГруппа обязательно установите флаг «Поиск».СоздатьГруппу() для всех папок.---
Чтобы больше не сталкиваться с проблемой «перепутавшихся» элементов и групп, придерживайтесь золотых стандартов настройки правил обмена в «Конвертации данных 2»:
ЭтоГруппа.ЭтоГруппа в таблице ПКС (Правил конвертации свойств).Мы проанализировали причины блокировки изменения признака папки в 1С и разобрали три практических способа восстановления иерархии справочников. Выбирайте программный способ пересоздания по GUID для рабочих баз без прямого доступа к СУБД, используйте SQL-запросы для быстрой реанимации крупных серверных баз или прибегайте к полному перезапуску обмена, если данные еще не обросли транзакционной историей.