The WriteXmlSchema and ReadXmlSchema methods provide an easy way to serialize a DataTable schema to transportable format. This is convenient if you want to pass around a schema definition for a data table between applications in your code.
The snippets of code below have been extracted from a unit test the full source of which is here these snippets provide a working example of how the WriteXmlSchema and ReadXmlSchema work.
First we need to define a Data Table. We will define one in C# but this could easily just come from a database query. Our table will look like
TestTable
| ColName | Type | Constraint |
| testInt | Int | PrimaryKey not null |
| testString | string | |
| testStringWithConstraint | String | MaxLength = 100 |
| testNonNullString | String | Not Null |
| testDateTime | DateTime | |
The C# Code to setup this data structure is as follows:
DataTable dt1 = new DataTable("TestTable");
DataColumn testIntPk = dt1.Columns.Add("testInt", typeof(int));
dt1.PrimaryKey = (new DataColumn[] { testIntPk });
dt1.Columns.Add("testString", typeof (string));
DataColumn testStringWithConstraint = dt1.Columns.Add("testStringWithConstraint", typeof(string));
testStringWithConstraint.MaxLength = 100;
DataColumn testNonNullString = dt1.Columns.Add("testNonNullString", typeof(string));
testNonNullString.AllowDBNull = false;
dt1.Columns.Add("testDateTime", typeof (DateTime));
dt1.AcceptChanges();
Once we have the Table structure setup we can invoke WriteXmlSchema method. The WriteXmlSchema has several overloads one which includes WriteXmlSchema(String) however I have elected to demonstrate using WriteXmlSchema(TextWriter).
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
dt1.WriteXmlSchema(writer);
string schemaAsString = sb.ToString();
Trace.WriteLine(schemaAsString);
writer.Close();
After this code has run the result of calling then WriteXmlSchema the string schemaAsString has the following value:
<?xml version="1.0" encoding="utf-16"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="TestTable" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="TestTable">
<xs:complexType>
<xs:sequence>
<xs:element name="testInt" type="xs:int" />
<xs:element name="testString" type="xs:string" minOccurs="0" />
<xs:element name="testStringWithConstraint" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="100" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="testNonNullString" type="xs:string" />
<xs:element name="testDateTime" type="xs:dateTime" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//TestTable" />
<xs:field xpath="testInt" />
</xs:unique>
</xs:element>
</xs:schema>
You can see all the elements specified for the datatable have been included in the XSD (ie xml) for the dataTable.
To reverse the process we can read the XML schema from the string into a new instance of a data Table as follows:
DataTable dt2 = new DataTable();
StringReader reader = new StringReader(schemaAsString);
dt2.ReadXmlSchema(reader);
At this point the DataTable which is read in from the string will be exactly the same as the version which was serialized. To check on this we have the following Unit Test Assertions which ensure the deserialized version is identical in all aspects.
// now Assert dt = dt2
// check the Name of table
Assert.AreEqual(dt1.TableName, dt2.TableName);
// check number of colunms is the same
Assert.AreEqual(dt1.Columns.Count, dt2.Columns.Count);
// names are all the colunm names are the same
foreach (DataColumn dc1 in dt1.Columns)
{
Assert.IsNotNull(dt2.Columns[dc1.ColumnName]);
}
// check the primary key
Assert.AreEqual(dt1.PrimaryKey[0].ColumnName, dt2.PrimaryKey[0].ColumnName);
// check the max length constraint
Assert.AreEqual(dt1.Columns["testStringWithConstraint"].MaxLength,
dt2.Columns["testStringWithConstraint"].MaxLength);
// check the null constraint
Assert.AreEqual(dt1.Columns["testNonNullString"].AllowDBNull,
dt2.Columns["testNonNullString"].AllowDBNull);