3

Normally I try to stay well clear of DataSets and DataTables, but we currently have a requirement where it seems to make sense to use them.

I'm having some problems serializing a DataTable when the DataColumn name contains a space and the type of the column is a custom type that I have written.

It looks like the serialization process is spuriously adding escape characters to the encoded column name, almost as if it's been encoded twice. It only happens if I use my own type as the data type of the column, using typeof(object) works fine.

Is this a standard feature, and if so does anyone know of any way around it?

The following code sample demonstrates the issue. The column called "NameWithoutSpaces" is encoded just as "NameWithoutSpaces" whereas "Name With Spaces" is encoded as "Name_x005F_x0020_With_x005F_x0020_Spaces" with extra x005F characters

When writing out the schema the column correctly gets encoded as "Name_x0020_With_x0020_Spaces", which I guess is the cause of the issue as this column is blank once the Read* methods are called.

According to the documentation for XmlConvert.EncodeName the space should be encoded with x0020 and the 005F is used as an escap char. So, the result we're getting seems to be what would happen if the text had been encoded twice through this mechanism.

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; }
    }
}
JonC
  • 809
  • 8
  • 18

2 Answers2

0

You must set the Serializable attribute to your custom object class..

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

Here's an article for you http://www.codeproject.com/Articles/1789/Object-Serialization-using-C

banging
  • 2,540
  • 1
  • 22
  • 26
0

Not only should you use the Serializable attribute you also need to implement IXmlSerializable for the custom type to serialize properly in a dataset. My datasets were coming back with blank columns until I implemented the IXmlSerializable.

UDTs must support conversion to and from the xml data type by conforming to the contract for XML serialization. The System.Xml.Serialization namespace contains classes that are used to serialize objects into XML format documents or streams. You can choose to implement xml serialization by using the IXmlSerializable interface, which provides custom formatting for XML serialization and deserialization.

In addition to performing explicit conversions from UDT to xml, XML serialization enables you to:

Use Xquery over values of UDT instances after conversion to the xml data type.

Use UDTs in parameterized queries and Web methods with Native XML Web Services in SQL Server.

Use UDTs to receive a bulk load of XML data.

Serialize DataSets that contain tables with UDT columns.

UDTs are not serialized in FOR XML queries. To execute a FOR XML query that displays the XML serialization of UDTs, explicitly convert each UDT column to the xml data type in the SELECT statement. You can also explicitly convert the columns to varbinary, varchar, or nvarchar.

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

Advantages of using IXmlSerializable http://technet.microsoft.com/en-us/library/ms131082.aspx

Isaac
  • 121
  • 8