How to use the WriteXmlSchema and ReadXmlSchema methods of the .Net DataTable

by Kevin Bosch 7. August 2010 20:13

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

ColNameTypeConstraint
testIntIntPrimaryKey not null
testStringstring
testStringWithConstraintStringMaxLength = 100
testNonNullStringStringNot Null
testDateTimeDateTime

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);

Tags: ,

DataTable

Comments


August 18. 2010 08:14
Webhostingpad Coupons
Ah, I discover the actual fact has limitless debatable points. I don't need to argue with you here, but I have my very own opinions as well. Anyway, you probably did a great job in writing the post, and wish to praise you for the onerous work. Sustain with the great job!


September 4. 2010 17:40
Jacklyn Caneza
This is my first time i visit here. I found so many interesting stuff in your blog especially its discussion. From the tons of comments on your articles, I guess I am not the only one having all the enjoyment here! keep up the good work


September 7. 2010 06:56
Owen Catts
Having been simply looking at related blog posts intended for the project research and My partner and i happened to stumble on yours. Many thanks for this practical information!

Comments are closed

Calendar

<<  February 2012  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
2728291234
567891011

View posts in large calendar
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012 Code Associate