Почему мой DataTable не сериализуется правильно, когда имена столбцов содержат пробелы?

Обычно я стараюсь держаться подальше от DataSetс и DataTables, но в настоящее время у нас есть требование, когда представляется целесообразным их использовать.

У меня проблемы с сериализацией DataTable когда DataColumn name содержит пробел, а тип столбца - это пользовательский тип, который я написал.

Похоже, что процесс сериализации спонтанно добавляет escape-символы к закодированному имени столбца, почти как если бы он был закодирован дважды. Это происходит, только если я использую свой собственный тип в качестве типа данных столбца, используя typeof(object) работает отлично.

Это стандартная функция, и если да, то знает ли кто-нибудь об этом?

Следующий пример кода демонстрирует проблему. Столбец с именем "NameWithoutSpaces" кодируется так же, как "NameWithoutSpaces", тогда как "Имя с пробелами" кодируется как "Name_x005F_x0020_With_x005F_x0020_Spaces" с дополнительными символами x005F.

При записи схемы столбец корректно кодируется как "Name_x0020_With_x0020_Spaces", что, как мне кажется, является причиной проблемы, поскольку этот столбец пуст после вызова методов Read*.

В соответствии с документацией для XmlConvert.EncodeName пространство должно быть закодировано с помощью x0020, а 005F используется в качестве escape-символа. Таким образом, результат, который мы получаем, выглядит так, как если бы текст был кодирован дважды с помощью этого механизма.

namespace DataTableSerialization
{
    using System.Data;

    class Program
    {
        static void Main(string[] args)
        {
            var dataTable = CreateDataTable();

            var row1 = dataTable.NewRow();
            row1.ItemArray = new object[] { new Item {Value = "Data1"}, new Item {Value = "Data2"} };
            dataTable.Rows.Add(row1);

            dataTable.WriteXml(@"C:\datatable.xml");
            dataTable.WriteXmlSchema(@"C:\schema.xml");

            var dataTable2 = new DataTable();
            dataTable2.ReadXmlSchema(@"C:\schema.xml");
            dataTable2.ReadXml(@"C:\datatable.xml");
        }

        private static DataTable CreateDataTable()
        {
            var table = new DataTable { TableName = "Table" };

            var col1 = new DataColumn("NameWithoutSpaces", typeof(Item));
            var col2 = new DataColumn("Name With Spaces", typeof(Item));

            table.Columns.Add(col1);
            table.Columns.Add(col2);

            return table;
        }
    }

    public class Item
    {
        public string Value { get; set; }
    }
}

2 ответа

Вы должны установить атрибут Serializable в свой класс объектов.

[Serializable]
public class Item     
{
    public string Value { get; set; }
} 

Вот статья для вас http://www.codeproject.com/Articles/1789/Object-Serialization-using-C

Вы должны не только использовать атрибут Serializable, но и реализовать IXmlSerializable для правильной сериализации пользовательского типа в наборе данных. Мои наборы данных возвращались с пустыми столбцами, пока я не реализовал IXmlSerializable.

UDT должны поддерживать преобразование в тип данных xml и обратно в соответствии с контрактом на сериализацию XML. Пространство имен System.Xml.Serialization содержит классы, которые используются для сериализации объектов в документы или потоки в формате XML. Вы можете реализовать сериализацию xml с помощью интерфейса IXmlSerializable, который обеспечивает настраиваемое форматирование для сериализации и десериализации XML.

Помимо выполнения явных преобразований из UDT в xml, сериализация XML позволяет вам:

Используйте Xquery для значений экземпляров UDT после преобразования в тип данных xml.

Используйте UDT в параметризованных запросах и веб-методах с собственными веб-службами XML в SQL Server.

Используйте UDT для получения массовой загрузки данных XML.

Сериализация DataSets, которые содержат таблицы со столбцами UDT.

UDT не сериализуются в запросах FOR XML. Чтобы выполнить запрос FOR XML, который отображает XML-сериализацию UDT, явным образом преобразуйте каждый столбец UDT в тип данных xml в инструкции SELECT. Вы также можете явно преобразовать столбцы в varbinary, varchar или nvarchar.

http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

Преимущества использования IXmlSerializable http://technet.microsoft.com/en-us/library/ms131082.aspx

Другие вопросы по тегам