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

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

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

Похоже, что процесс сериализации спонтанно добавляет 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 ]

0 голосов
/ 18 августа 2012

Мало того, что вы должны использовать атрибут 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.

Сериализация наборов данных, содержащих таблицы со столбцами 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

0 голосов
/ 25 апреля 2012

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

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

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

...