Почему мой DataTable не сериализуется правильно, когда имена столбцов содержат пробелы?
Обычно я стараюсь держаться подальше от DataSet
с и DataTable
s, но в настоящее время у нас есть требование, когда представляется целесообразным их использовать.
У меня проблемы с сериализацией 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