ReadAndWriteXmlSchemas
====================

This application illustrates the use and results from the ReadXmlSchema() and WriteXmlSchema() methods of the DataSet class.

The <Load Data> button calls a method that invokes ReadXml() to load data from an XML data file, Products.XML.  Optionally, the method first calls ReadXmlSchema() to load schema information from an XML schema definition file, dsProduct.xsd.

    Private Function LoadData() As Boolean
        objdsProduct = Nothing             'Clear any existing version
        objdsProduct = New DataSet    'Create a new DataSet

        'Optionally, load an external schema
        Try
            If Me.chkLoadSchema.Checked Then
                objdsProduct.ReadXmlSchema("..\dsProduct.xsd")
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Return False
        End Try

        'Fill the DataSet
        Try
            objdsProduct.ReadXml("Products.xml")
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        Return True

    End Function

Products.XML does not contain schema information.   Therefore when ReadXml() is called to load the data, if the option to select schema information has not been selected, ReadXml() must infer the schema from the incoming data. Thus in this circumstances the ReadXml("Products.xml") call is equivalent to the more explicit ReadXml("Products.xml", XmlReadMode.InferSchema).  You can see this if you click the <Write Current Schema to File:> button.  The Click event handler for that button executes the following statement:

        objdsProduct.WriteXmlSchema(Me.txtOutputFile.Text)

If you then double-click the file "dsProduct_OUT.xsd" in the Solution Explorer to open it, you will see that all columns have been typed as strings:

              <xs:element name="ProductID" type="xs:string" minOccurs="0" />
              <xs:element name="ProductName" type="xs:string" minOccurs="0" />
              <xs:element name="UnitPrice" type="xs:string" minOccurs="0" />
              <xs:element name="UnitsInStock" type="xs:string" minOccurs="0" />
              <xs:element name="Discontinued" type="xs:string" minOccurs="0" />
              
If, on the other hand, you check the "Read External Schema Before Loading Data" checkbox so that schema information gets loaded from dsProduct.xsd before the data is loaded, and then write the dsProduct_OUT.xsd file, you can observe that columns are now typed as you find them in the Products table of the Northwind database:

              <xs:element name="ProductID" msdata:DataType="System.Guid, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
              <xs:element name="ProductName" type="xs:string" minOccurs="0" />
              <xs:element name="UnitPrice" type="xs:decimal" minOccurs="0" />
              <xs:element name="UnitsInStock" type="xs:integer" minOccurs="0" />
              <xs:element name="Discontinued" type="xs:boolean" minOccurs="0" />


Effect of the Schema Info on the Data Displayed in the DataGrid
=============================================
You can see the effect of loading the schema info by observing the loaded data as displayed in the DataGrid.  When all columns are typed as strings, the Discontinued column (which is Boolean in the Northwind database and in the dsProduct.xsd schema definition) displays as the text strings "True" or "False".  When schema information is loaded from dsProduct.xsd rather than inferred, the Discontinued column displays as a checkbox: the DataGrid's default display for Boolean columns.

Note also the differences in sorting behavior. Selecting the checkbox "Sort on UnitsInStock" runs a SortData() method that sorts data in the DataGrid's datasource, the DefaultView of the loaded table.

    Private Sub SortData()
        If chkSortOnUnitsInStock.Checked Then
            objdsProduct.Tables("Product").DefaultView.Sort = "UnitsInStock"
        Else
            objdsProduct.Tables("Product").DefaultView.Sort = ""
        End If
    End Sub

When the schema is inferred, UnitsInStock is typed as a string, and sorting follows the ASCII order of numeric characters.  Thus a product with "115" units in stock sorts ahead of one with "13" or "24".  This is probably not what you really want to see!

On the other hand, when the schema is loaded from dsProduct.xsd, UnitsInStock is typed as an integer, and the sort order is the correct numeric one:  13, 24, then 115.


Exploration Prescription
========================
Perform the following steps to see the result of applying the external schema:

1. Load the data with the checkboxes labelled "Read External Schema Before Loading Data" and "Sort on UnitsInStock" NOT checked.  Note the order of records by examining the UnitsInStock column.

2. Check the "Sort on UnitsInStock" checkbox and note the new sort order. Records are in ascending order by the ASCII value of the values in the UnitsInStock column.

3. Leaving the checkbox labelled "Sort on UnitsInStock" checked, now check the checkbox labelled "Read External Schema Before Loading Data".  Click the <Load Data> button to recreate the DataSet, to read the external schema data into it, and to reload the data.  Note the sort order now:  records are in the correct ascending numerical order by UnitsInStock.

Try the following additional experiments to learn more:

1. With the checkbox labelled "Read External Schema Before Loading Data"  NOT checked, click the <Load Data> button.  Then click the <Write Current Schema to File:> button to write the DataSet's schema to a disk file using the WriteXmlSchema() method.  Examine the resulting schema file (available in the Solution Explorer under "Solution Items" if you left the output filename at its default value; otherwise available in the bin folder for the project).  Note that all data types are strings. Now close the schema file you had the program write.

2. Reload the data with the "Read External Schema Before Loading Data"  checkbox  CHECKED.  Again write the schema to a file. Examine the new version and note the changed data types.

