Имя: Пароль:
1C
1С v8
Ошибка сериализации пустых табличных частей
0 vitek1
 
09.06.15
16:28
Ошибка заключается при десериализации объекта с пустой табличной частью, если в базе эта таб. часть заполнена. В этом случае заполненная таб. часть не очищается.
Поясню на примере.
Есть демо база, в ней док-т Поступление товаров и услуг с 2-ми таб. частями: Товары и Услуги (скрин Конфигуратор).
Для сериализации и десериализации использую коды (http://pixs.ru/showimage/RRRSRRSSRS_2575358_17611037.png):

[code]
&НаСервере
Процедура ВыгрузитьНаСервере()
      
      ЗаписьXML = Новый ЗаписьXML;
      ЗаписьXML.ОткрытьФайл(ИмяФайла, "windows-1251");
      ЗаписьXML.ЗаписатьОбъявлениеXML();
      ЗаписьXML.ЗаписатьНачалоЭлемента("Данные");
      СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Документ.ПолучитьОбъект());
      ЗаписьXML.ЗаписатьКонецЭлемента();
      ЗаписьXML.Закрыть();
      
КонецПроцедуры

&НаКлиенте
Процедура Выгрузить(Команда)
      ВыгрузитьНаСервере();
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьНаСервере()
      
      ЧтениеXML = Новый ЧтениеXML;
      ЧтениеXML.ОткрытьФайл(ИмяФайла);
      ЧтениеXML.ПерейтиКСодержимому();
      ЧтениеXML.Прочитать();
      ДокументОбъект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
      ДокументОбъект.ОбменДанными.Загрузка = Истина;
      ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
      ЧтениеXML.Прочитать();
      ЧтениеXML.Закрыть();
      
      Документ = ДокументОбъект.Ссылка;
      
КонецПроцедуры

&НаКлиенте
Процедура Загрузить(Команда)
      ЗагрузитьНаСервере();
КонецПроцедуры
[\code]

Сериализуем док-т с пустой таб. частью Товары, получаем xml:

[code]
<?xml version="1.0" encoding="windows-1251"?>
<Данные>
      <DocumentObject.ПоступлениеТоваровИУслуг xmlns="http://v8.1c.ru/8.1/data/enterprise/current-config"; xmlns:xs=" http://www.w3.org/2001/XMLSchema »»" xmlns:xsi=" http://www.w3.org/2001/XMLSchem... »»">
            <Ref>3580c752-0e94-11e5-a111-c8d3a3841935</Ref>
            <DeletionMark>false</DeletionMark>
            <Date>2015-06-09T14:23:20</Date>
            <Number>000000001</Number>
            <Posted>true</Posted>
            <Услуги>
                  <Номенклатура>3580c751-0e94-11e5-a111-c8d3a3841935</Номенклатура>
            </Услуги>
      </DocumentObject.ПоступлениеТоваровИУслуг>
</Данные>
[\code]

далее добавляем одну или несколько строк в таб. вчасть Товары в этот же док-т. Загружаем полученный ранее xml файл. После оператора ДокументОбъект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML); в отладчике видим, что ТЧ Товары действительно пустая (http://pixs.ru/showimage/RSRRRRR.pn_1376624_17611041.png). После строки Записать тоже у объекта Товары пустая (а Ссылка.Товары заполнена). Но после отработки кода таб. часть Товары остается заполненной (при просмотре в режиме предприятия или кодом выполнить ПолучитьОбъект()).
Никаких отмен транзакций нет, загружаемые поля из файла модифицируются (например, если в файле руками поменять номер, то после загрузки он действительно меняется).
Для эксперимента пробовал в xml файл руками добавить <Товары/> перед тэгом услуги, тогда ругается рпи чтении.
Выкладываю также саму базу.

Как при этом можно использовать механизм сериализации серез СериализаторXDTO, если он не очищает пустые таб. части при загрузке?
Можно обойти эту ошибку без "ручной" сериализации объектов.

PS. ЗаписатьXML (глобавльный контекст, а не метод СериализаторXDTO) работает нормально, он добавляет <Товары/>, но он не сериализует, например, таблицу значений и прочие типы.
1 MrStomak
 
09.06.15
16:32
XML и XDTO-сериализация объектов с табличными частями
Код ошибки: 30019662
Код(ы) обращения: SW915344, CSR-2226
Статус: Исправлена в будущей версии Зарегистрирована: 05.03.2015
Описание:
При чтении из XML (средствами XML и XDTO-сериализации) объектов с табличными частями, в случае, если в данных XML не содержится строк той или иной табличной части (табличная часть пустая), для существующих в БД объектов, при записи - очистки данной табличной части не произойдет.

Способ обхода:
Перед записью объекта для пустых табличных частей выполнять явную очистку при помощи метода Очистить.
2 vitek1
 
09.06.15
19:04
спасибо за ответ, очень помогли.

странно, что с 05.03.2015 1С не устранило ошибку, релизы-то выходили. Активно развивают и рекламируют универсальные кроссплатформенные средства обмена xml и json, но с этой ошибкой удобным и простым типовым механизмом пользоваться нельзя.

Для таких же несчастных, как я выкладываю универсальную процедуру, которую надо добавить после

ДокументОбъект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);

для обхода ошибки. Вызываем
ОчиститьПустыеТабличныеЧасти(ДокументОбъект );

Процедура ОчиститьПустыеТабличныеЧасти(Значение) Экспорт
    
    Если ЭтоОбъект(Значение) Тогда
        МетаданныеОбъекта = Значение.Метаданные();
        Для каждого ТЧ Из МетаданныеОбъекта.ТабличныеЧасти Цикл
            Если Значение[ТЧ.Имя].Количество() = 0 Тогда
                Значение[ТЧ.Имя].Очистить();
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

// Проверка того, что переданный тип является объектым типом данных.
//
// Возвращаемое значение:
//  Булево.
//
Функция ЭтоОбъект(Значение) Экспорт
    
    Тип = XMLТипЗнч(Значение).ИмяТипа;
    
    Возврат Лев(Тип, 14) = "CatalogObject."    
        ИЛИ Лев(Тип, 15) = "DocumentObject."
        ИЛИ Лев(Тип, 19) = "ExchangePlanObject.";        
    
КонецФункции

у меня используется для мобильного приложения. Для настольного функцию ЭтоОбъект() расширить на остальные типы данных
Глупец, лишенный способности посмеяться над собой вместе с другими, не сможет долго выносить программирование. Фредерик Брукс-младший