Как организовать перенос данных между базами 1С с разными версиями конфигурации?

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

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

Разберем, почему стандартные механизмы дают сбой и как реализовать надежный обмен данными без падений из-за различий в структуре объектов.

Почему стандартный СериализаторXDTO вызывает ошибки при несовпадении версий?

Проанализируем работу механизма СериализаторXDTO. При выполнении методов СериализаторXDTO.ПрочитатьXML() или ПрочитатьJSON() с передачей сериализатора платформа обращается к фабрике XDTO и фиксированному пакету текущей конфигурации (http://v8.1c.ru/8.1/data/enterprise/current-config).

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

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

Решение: Десериализация через нативный JSON и метод ЗаполнитьЗначенияСвойств

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

Разберем по шагам, как построить надежный процесс чтения и записи данных:

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

Посмотрим на пример кода, реализующего безопасную загрузку элемента справочника из десериализованной структуры JSON:


// Предположим, что ДанныеЭлемента — это десериализованная Структура из JSON
ИмяСправочника = "ШаблоныНастроек";
МетаданныеОбъекта = Метаданные.Справочники.Найти(ИмяСправочника);

Если МетаданныеОбъекта <> Неопределено Тогда
    // Ищем объект по ключевому реквизиту (например, Код)
    СсылкаНаОбъект = Справочники[ИмяСправочника].НайтиПоКоду(ДанныеЭлемента.Код);
    
    Если СсылкаНаОбъект.Пустая() Тогда
        ОбъектБазы = Справочники[ИмяСправочника].СоздатьЭлемент();
    Иначе
        ОбъектБазы = СсылкаНаОбъект.ПолучитьОбъект();
    КонецЕсли;

    // Безопасно заполняем совпадающие реквизиты шапки
    ЗаполнитьЗначенияСвойств(ОбъектБазы, ДанныеЭлемента);

    // Обрабатываем табличные части
    Если ДанныеЭлемента.Свойство("ТабличныеЧасти") Тогда
        Для Каждого ОписаниеТЧ Из ДанныеЭлемента.ТабличныеЧасти Цикл
            ИмяТЧ = ОписаниеТЧ.Ключ;
            СтрокиТЧ = ОписаниеТЧ.Значение;

            // Проверяем, существует ли такая ТЧ в текущей конфигурации
            Если МетаданныеОбъекта.ТабличныеЧасти.Найти(ИмяТЧ) <> Неопределено Тогда
                ТЧОбъекта = ОбъектБазы[ИмяТЧ];
                ТЧОбъекта.Очистить();
                
                Для Каждого СтрокаИсточника Из СтрокиТЧ Цикл
                    НоваяСтрока = ТЧОбъекта.Добавить();
                    ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
                КонецЦикла;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;

    ОбъектБазы.Записать();
КонецЕсли;

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

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

Проверим доступность типа загружаемого значения:


РеквизитМетаданных = МетаданныеОбъекта.Реквизиты.Найти("ВерсияФормата");
Если РеквизитМетаданных <> Неопределено Тогда
    ТипЗначенияИзФайла = ТипЗнч(ДанныеЭлемента.ВерсияФормата);
    
    // Проверяем, поддерживает ли реквизит приемника тип загружаемого значения
    Если РеквизитМетаданных.Тип.СодержитТип(ТипЗначенияИзФайла) Тогда
        ОбъектБазы.ВерсияФормата = ДанныеЭлемента.ВерсияФормата;
    КонецЕсли;
КонецЕсли;

Альтернативные архитектурные подходы

Если проект требует более формализованного обмена или планируется постоянная синхронизация, рассмотрим альтернативные варианты:

  1. Выделенный независимый XDTO-пакет: Вместо использования типов конфигурации создается собственный XDTO-пакет. В схеме для необязательных полей указывается директива minOccurs="0" или применяются типы anyType / anySimpleType. При изменении реквизитного состава в базах сам контракт обмена не нарушается, и методы XDTO продолжают работать без сбоев.
  2. Формат EnterpriseData и КД 3.0: Если в конфигурацию внедрена библиотека стандартных подсистем (БСП), обмен можно построить на базе универсального формата EnterpriseData. В этом случае версионирование и адаптация под структуру конкретной базы берутся на себя встроенными обработчиками конвертации.
  3. Интерактивная загрузка через правила конвертации (КД 2.1): Использование типовой обработки Универсальный обмен данными в формате XML позволяет задействовать обработчики событий (ПередЗагрузкой, ПриЗагрузке), где программно анализируются метаданные приемника, а пользователь может вручную отобрать необходимые данные перед фактической записью.
← На главную