При длительном сопровождении нетиповых конфигураций «1С:Предприятие» разработчики часто сталкиваются с крайне неприятной ситуацией. В процессе доработки конфигурации определенный объект (например, справочник, документ, регистр накопления или его реквизит) сначала удаляется из дерева метаданных, а затем создается заново с точно таким же именем. Внешне конфигурация выглядит корректно, однако при попытке обновить конфигурацию поставщика или объединить её с эталонной базой платформа начинает вести себя непредсказуемо: она пытается полностью удалить существующий объект вместе со всеми накопленными в СУБД данными и создать на его месте новый пустой объект.
В этой статье мы подробно разберем, почему возникает эта проблема, как устроены внутренние механизмы платформы «1С:Предприятие», и рассмотрим несколько надежных практических способов исправления ситуации без потери ценных данных в рабочей базе.
Давайте разберем внутреннюю кухню платформы 1С. Каждый объект метаданных в конфигурации идентифицируется двумя параметрами:
Справочник.Номенклатура) — используется разработчиками в коде и отображается в интерфейсе._Reference25).Когда мы выполняем обычное сравнение двух конфигураций через файлы .cf, платформа пытается сопоставить объекты в первую очередь по имени. Но при обновлении информационной базы, находящейся на поддержке, сопоставление выполняется строго по UUID.
Если в процессе разработки объект был удален и создан заново под тем же именем, его UUID изменился. С точки зрения СУБД и механизма обновления 1С это абсолютно другой, новый объект. При обновлении конфигурации базы данных платформа выполнит две операции:
Наша задача — восстановить соответствие идентификаторов между рабочей базой и конфигурацией поставщика. Ниже мы рассмотрим наиболее эффективные методики решения этой проблемы.
---
Начиная с версии платформы 8.3, разработчикам доступен мощный инструмент — выгрузка конфигурации в текстовые файлы XML. Этот способ является наиболее технологичным и чистым, так как позволяет точечно «подменить» съехавшие UUID на оригинальные UUID из конфигурации поставщика без написания сложных обработок переноса данных.
Рассмотрим этот процесс по шагам:
.cf.C:\XML_Work)..cf. Создайте для нее пустую базу, откройте ее конфигуратор и также выгрузите в другую папку (например, C:\XML_Vendor).Catalog.Номенклатура.xml (или аналогичный файл для регистра накопления/сведений).<uuid>).
Скопируйте UUID из файла конфигурации поставщика (папка C:\XML_Vendor) и вставьте его вместо старого UUID в файл вашей рабочей конфигурации (папка C:\XML_Work). Сохраните изменения.
C:\XML_Work.---
Если вы не хотите работать напрямую с XML-файлами конфигурации или версия платформы накладывает свои ограничения, можно прибегнуть к проверенной временем классической схеме переноса данных через временные объекты.
Проанализируем этот алгоритм:
Справочник.Номенклатура в Справочник.Удалить_Номенклатура.Номенклатура в вашей базе больше нет (он переименован), платформа автоматически создаст новый пустой справочник Номенклатура с правильным UUID, соответствующим конфигурации поставщика.ЗаменитьСсылки().Удалить_ можно безопасно удалить из конфигурации при следующем обновлении.Рассмотрим пример кода для переноса данных и автоматической замены ссылок:
Процедура ПеренестиДанныеИЗаменитьСсылки() Экспорт
// Выбираем все элементы из старого переименованного справочника
ВыборкаСтарая = Справочники.Удалить_Номенклатура.Выбрать();
Пока ВыборкаСтарая.Следующий() Цикл
// Исключаем группы, если справочник иерархический
Если ВыборкаСтарая.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
// Пытаемся найти уже созданный аналог по ключевому реквизиту (например, Код или Артикул)
НоваяСсылка = Справочники.Номенклатура.НайтиПоРеквизиту("Код", ВыборкаСтарая.Код);
Если НоваяСсылка.Пустая() Тогда
// Создаем новый элемент с правильным UUID
НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
ЗаполнитьЗначенияСвойств(НовыйОбъект, ВыборкаСтарая);
// Если у справочника есть родитель, его тоже нужно корректно перенести
Если ЗначениеЗаполнено(ВыборкаСтарая.Родитель) Тогда
// Здесь должна быть логика поиска/создания группы-родителя
КонецЕсли;
НовыйОбъект.Записать();
НоваяСсылка = НовыйОбъект.Ссылка;
КонецЕсли;
// Подготавливаем таблицу для замены ссылок во всей базе данных
ТаблицаЗамены = Новый ТаблицаЗначений;
ТаблицаЗамены.Колонки.Добавить("ИсходнаяСсылка");
ТаблицаЗамены.Колонки.Добавить("НоваяСсылка");
СтрокаЗамены = ТаблицаЗамены.Добавить();
СтрокаЗамены.ИсходнаяСсылка = ВыборкаСтарая.Ссылка;
СтрокаЗамены.НоваяСсылка = НоваяСсылка;
// Выполняем поиск и замену ссылок средствами платформы
Попытка
ЗаменитьСсылки(ТаблицаЗамены);
Сообщить("Успешно заменена ссылка для: " + ВыборкаСтарая.Наименование);
Исключение
ЗаписьЖурналаРегистрации("ПереносДанных", УровеньЖурналаРегистрации.Ошибка,,,
ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
КонецПроцедуры
---
В некоторых случаях, если рассинхронизация UUID произошла при сравнении с внешним файлом конфигурации (например, при выборочном переносе доработок из тестовой базы), мы можем воспользоваться встроенным интерактивным механизмом платформы.
Выполним следующие действия:
Важное примечание: Этот способ отлично подходит для разового переноса кода и неструктурных изменений (форм, макетов, модулей). Однако он не решает проблему кардинально на уровне конфигурации базы данных, если вы планируете в дальнейшем обновляться стандартными файлами обновлений (.cfu) от поставщика. Для долгосрочного решения лучше использовать Способ 1 или Способ 2.
---
Для того чтобы избежать подобных критических проблем в будущем, мы рекомендуем соблюдать простые правила разработки в среде «1С:Предприятие 8»:
Удалить_ и снимите с него все ссылки, но не удаляйте физически, пока не убедитесь, что его замена полностью протестирована.