Как правильно сохранить объект XDTO в регистр сведений и восстановить его без потери типов?

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

При интеграции систем или работе со сложными структурами данных программисты 1С часто сталкиваются с необходимостью временного или постоянного хранения объектов XDTODataObject в базе данных. Оптимальным местом для этого является Регистр сведений. Однако в процессе реализации возникают две основные сложности: ошибка несоответствия типов при записи и превращение всех данных в строки при чтении. Разберем пошагово, как реализовать этот механизм правильно.

Выясним причину ошибки: СериализаторXDTO против ФабрикиXDTO

Первая проблема, с которой сталкиваются разработчики — это использование объекта СериализаторXDTO для записи уже существующего объекта XDTO. Проанализируем ситуацию: метод СериализаторXDTO.ЗаписатьXML() предназначен для преобразования прикладных типов 1С (таких как СправочникОбъект, ДокументОбъект, Структура или ТаблицаЗначений) в формат XML на основе имеющейся модели XDTO. Если мы попытаемся передать в него уже готовый ОбъектXDTO, система выдаст ошибку «Несоответствие типов (параметр номер '2')».

Для работы с объектами, которые уже являются частью модели XDTO, необходимо использовать глобальный объект ФабрикаXDTO или созданную программно фабрику. Именно метод ФабрикаXDTO.ЗаписатьXML() корректно обработает ваш объект.

Шаг 1. Подготовка регистра сведений

Перед тем как писать код, настроим структуру регистра. Рассмотрим наиболее эффективный вариант:

  1. Создадим новый регистр сведений (например, ОчередьСообщенийXDTO).
  2. В качестве измерений добавим уникальный идентификатор или ссылку на объект, к которому привязаны данные.
  3. Создадим ресурс с именем ДанныеОбъекта и типом ХранилищеЗначения. Использование хранилища позволяет упаковать XML-строку в бинарные данные, что экономит место и позволяет хранить данные любого объема.

Шаг 2. Корректная запись объекта XDTO

Рассмотрим процесс сериализации и записи. Нам нужно превратить объект в строку XML, а затем поместить эту строку в ХранилищеЗначения. Чтобы уменьшить объем занимаемой памяти, применим максимальное сжатие.


// Предположим, что ОбъектXDTO у нас уже сформирован
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();

// Используем Фабрику, а не Сериализатор
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);

СтрокаXML = ЗаписьXML.Закрыть();

// Создаем хранилище с высокой степенью сжатия (9)
НовоеХранилище = Новый ХранилищеЗначения(СтрокаXML, Новый СжатиеДанных(9));

// Записываем в регистр сведений
МенеджерЗаписи = РегистрыСведений.ОчередьСообщенийXDTO.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ID = Новый УникальныйИдентификатор();
МенеджерЗаписи.ДанныеОбъекта = НовоеХранилище;
МенеджерЗаписи.Записать();

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

Разберем проблему потери типизации: Почему все данные становятся строками?

Проанализируем типичную ситуацию: при восстановлении объекта через ФабрикаXDTO.ПрочитатьXML() все числа, даты и булевы значения превращаются в текст. Выясним причину: это происходит потому, что при чтении XML-данных фабрика не понимает, какой схеме (XSD) соответствует данный текст, если это явно не указано.

Если в самом XML-файле отсутствует атрибут xsi:type, или если фабрика не может сопоставить пространство имен (namespace) с имеющимися в системе пакетами XDTO, она интерпретирует все значения как универсальный строковый тип.

Шаг 3. Правильное чтение и восстановление типов

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

Посмотрим на пример правильного чтения данных из регистра:


// 1. Получаем данные из регистра
ЗаписьРегистра = РегистрыСведений.ОчередьСообщенийXDTO.СоздатьМенеджерЗаписи();
ЗаписьРегистра.ID = НужныйИдентификатор;
ЗаписьРегистра.Прочитать();

Если Не ЗаписьРегистра.Выбран() Тогда
    Возврат;
КонецЕсли;

// 2. Извлекаем строку из ХранилищаЗначения
СтрокаXML = ЗаписьРегистра.ДанныеОбъекта.Получить();

// 3. Настраиваем чтение
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);

// 4. Восстанавливаем объект с указанием типа
// Если схема в конфигурации, получаем тип по URI и локальному имени
ТипОбъекта = ФабрикаXDTO.Тип("http://www.your-namespace.com", "YourTypeName");
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML, ТипОбъекта);

Передача второго параметра ТипОбъекта в метод ПрочитатьXML заставляет фабрику жестко следовать структуре описания типов. В этом случае Дата останется датой, а Число — числом.

Работа с внешними схемами XSD

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

Если вы попытаетесь прочитать XML-строку, созданную по внешней схеме, используя глобальную ФабрикаXDTO, система не найдет описания типов и либо выдаст ошибку, либо вернет "плоский" строковый объект. Посмотрим, как создать временную фабрику для работы с регистром:


// Создаем фабрику на основе файла схемы
ПутьКСхеме = "C:\Schemas\MyData.xsd";
НаборСхем = Новый НаборСхемXML;
НаборСхем.Добавить(ПутьКСхеме);
МояФабрика = Новый ФабрикаXDTO(НаборСхем);

// Теперь используем именно эту фабрику для чтения
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
ОбъектXDTO = МояФабрика.ПрочитатьXML(ЧтениеXML);

Рекомендации по оптимизации

Проанализировав методы работы с большими объемами данных XDTO в регистрах, мы можем выделить несколько советов для повышения производительности:

Таким образом, мы выяснили, что для успешной работы с объектами XDTO в регистрах сведений ключевым является правильный выбор между СериализаторXDTO и ФабрикаXDTO, а также строгое соблюдение типизации через использование XSD-схем или явное указание типов при чтении.

← На главную