Normally I try to stay well clear of DataSet
s and DataTable
s, 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; }
}
}