Example of Synchronizing a DataSet with an XmlDataDocument
This section demonstrates one step in the processing of a purchase order, using a strongly typed DataSet synchronized with an XmlDataDocument. The examples that follow create a DataSet with a minimized schema that matches only a portion of the source XML document. The examples will use an XmlDataDocument to preserve the fidelity of the source XML document, enabling the DataSet to be used to expose a subset of the XML document.
The following XML document contains all the information pertaining to a purchase order: customer information, items ordered, shipping information, and so on.
<?xml version="1.0" standalone="yes"?>
<PurchaseOrder>
<Customers>
<CustomerID>CHOPS</CustomerID>
<Orders>
<OrderID>10966</OrderID>
<OrderDetails>
<OrderID>10966</OrderID>
<ProductID>37</ProductID>
<UnitPrice>26</UnitPrice>
<Quantity>8</Quantity>
<Discount>0</Discount>
</OrderDetails>
<OrderDetails>
<OrderID>10966</OrderID>
<ProductID>56</ProductID>
<UnitPrice>38</UnitPrice>
<Quantity>12</Quantity>
<Discount>0.15</Discount>
</OrderDetails>
<OrderDetails>
<OrderID>10966</OrderID>
<ProductID>62</ProductID>
<UnitPrice>49.3</UnitPrice>
<Quantity>12</Quantity>
<Discount>0.15</Discount>
</OrderDetails>
<CustomerID>CHOPS</CustomerID>
<EmployeeID>4</EmployeeID>
<OrderDate>1998-03-20T00:00:00.0000000</OrderDate>
<RequiredDate>1998-04-17T00:00:00.0000000</RequiredDate>
<ShippedDate>1998-04-08T00:00:00.0000000</ShippedDate>
<ShipVia>1</ShipVia>
<Freight>27.19</Freight>
<ShipName>Chop-suey Chinese</ShipName>
<ShipAddress>Hauptstr. 31</ShipAddress>
<ShipCity>Bern</ShipCity>
<ShipPostalCode>3012</ShipPostalCode>
<ShipCountry>Switzerland</ShipCountry>
</Orders>
<CompanyName>Chop-suey Chinese</CompanyName>
<ContactName>Yang Wang</ContactName>
<ContactTitle>Owner</ContactTitle>
<Address>Hauptstr. 29</Address>
<City>Bern</City>
<PostalCode>3012</PostalCode>
<Country>Switzerland</Country>
<Phone>0452-076545</Phone>
</Customers>
<Shippers>
<ShipperID>1</ShipperID>
<CompanyName>Speedy Express</CompanyName>
<Phone>(503) 555-9831</Phone>
</Shippers>
<Shippers>
<ShipperID>2</ShipperID>
<CompanyName>United Package</CompanyName>
<Phone>(503) 555-3199</Phone>
</Shippers>
<Shippers>
<ShipperID>3</ShipperID>
<CompanyName>Federal Shipping</CompanyName>
<Phone>(503) 555-9931</Phone>
</Shippers>
<Products>
<ProductID>37</ProductID>
<ProductName>Gravad lax</ProductName>
<QuantityPerUnit>12 - 500 g pkgs.</QuantityPerUnit>
<UnitsInStock>11</UnitsInStock>
<UnitsOnOrder>50</UnitsOnOrder>
<ReorderLevel>25</ReorderLevel>
</Products>
<Products>
<ProductID>56</ProductID>
<ProductName>Gnocchi di nonna Alice</ProductName>
<QuantityPerUnit>24 - 250 g pkgs.</QuantityPerUnit>
<UnitsInStock>21</UnitsInStock>
<UnitsOnOrder>10</UnitsOnOrder>
<ReorderLevel>30</ReorderLevel>
</Products>
<Products>
<ProductID>62</ProductID>
<ProductName>Tarte au sucre</ProductName>
<QuantityPerUnit>48 pies</QuantityPerUnit>
<UnitsInStock>17</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
</Products>
</PurchaseOrder>
One step in processing the purchase order information contained in the preceding XML document is for the order to be filled from the company's current inventory. The employee responsible for filling the order from the company's warehouse does not need to see the entire contents of the purchase order — they only need to see the product information for the order. To expose only the product information from the XML document, create a strongly typed DataSet with a schema, written as XML Schema definition language (XSD) schema, that maps to the products and quantities ordered. For more information about strongly typed DataSet objects, see Working with a Typed DataSet.
The following code shows the schema from which the strongly typed DataSet is generated for this sample.
<?xml version="1.0" standalone="yes"?>
<xs:schema id="OrderDetail"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:codegen="urn:schemas-microsoft-com:xml-msprop"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="OrderDetail" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="OrderDetails" codegen:typedName="LineItem" codegen:typedPlural="LineItems">
<xs:complexType>
<xs:sequence>
<xs:element name="OrderID" type="xs:int" minOccurs="0" codegen:typedName="OrderID"/>
<xs:element name="Quantity" type="xs:short" minOccurs="0" codegen:typedName="Quantity"/>
<xs:element name="ProductID" type="xs:int" minOccurs="0" codegen:typedName="ProductID"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Products" codegen:typedName="Product" codegen:typedPlural="Products">
<xs:complexType>
<xs:sequence>
<xs:element name="ProductID" type="xs:int" minOccurs="0" codegen:typedName="ProductID"/>
<xs:element name="ProductName" type="xs:string" minOccurs="0" codegen:typedName="ProductName"/>
<xs:element name="QuantityPerUnit" type="xs:string" minOccurs="0" codegen:typedName="QuantityPerUnit"/>
<xs:element name="UnitsInStock" type="xs:short" minOccurs="0" codegen:typedName="UnitsInStock"/>
<xs:element name="UnitsOnOrder" type="xs:short" minOccurs="0" codegen:typedName="UnitsOnOrder"/>
<xs:element name="ReorderLevel" type="xs:short" minOccurs="0" codegen:typedName="ReorderLevel"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1">
<xs:selector xpath=".//Products" />
<xs:field xpath="ProductID" />
</xs:unique>
<xs:keyref name="Relation1" refer="Constraint1" codegen:typedChildren="GetLineItems" codegen:typedParent="Product">
<xs:selector xpath=".//OrderDetails" />
<xs:field xpath="ProductID" />
</xs:keyref>
</xs:element>
</xs:schema>
Notice that only information from the OrderDetails and Products elements of the original XML document are included in the schema for the DataSet. Synchronizing the DataSet with an XmlDataDocument ensures that the elements not included in the DataSet will persist with the XML document.
With the strongly typed DataSet generated from the XML Schema (with a namespace of Northwind.FillOrder), a portion of the original XML document can be exposed by synchronizing the DataSet with the XmlDataDocument loaded from the source XML document. Note that the DataSet generated from the schema contains structure but no data. The data is filled in when you load the XML into the XmlDataDocument. If you attempt to load an XmlDataDocument that has been synchronized with a DataSet that already contains data, an exception will be thrown.
After the DataSet (and the XmlDataDocument) has been updated, the XmlDataDocument can then write out the modified XML document with the elements ignored by the DataSet still intact, as shown below. In the purchase order scenario, after the order items have been filled, the modified XML document can then be passed on to the next step in the order process, perhaps to the company's shipping department.
Imports System
Imports System.Data
Imports System.Xml
Imports Northwind.FillOrder
Public class Sample
Public Shared Sub Main()
Dim orderDS As OrderDetail = New OrderDetail
Dim xmlDoc As XmlDataDocument = New XmlDataDocument(orderDS)
xmlDoc.Load("Order.xml")
Dim myItem As OrderDetail.LineItem
Dim myProd As OrderDetail.Product
For Each myItem In orderDS.LineItems
myProd = myItem.Product
' Remove quantity from the current stock.
myProd.UnitsInStock = CType(myProd.UnitsInStock - myItem.Quantity, Short)
' If the remaining stock is less than the reorder level, order more.
If ((myProd.UnitsInStock + myProd.UnitsOnOrder) < myProd.ReorderLevel) Then
myProd.UnitsOnOrder = CType(myProd.UnitsOnOrder + myProd.ReorderLevel, Short)
End If
Next
xmlDoc.Save("Order_out.xml")
End Sub
End Class
[C#]
using System;
using System.Data;
using System.Xml;
using Northwind.FillOrder;
public class Sample
{
public static void Main()
{
OrderDetail orderDS = new OrderDetail();
XmlDataDocument xmlDoc = new XmlDataDocument(orderDS);
xmlDoc.Load("Order.xml");
foreach (OrderDetail.LineItem myItem in orderDS.LineItems)
{
OrderDetail.Product myProd = myItem.Product;
// Remove quantity from the current stock.
myProd.UnitsInStock = (short)(myProd.UnitsInStock - myItem.Quantity);
// If the remaining stock is less than the reorder level, order more.
if ((myProd.UnitsInStock + myProd.UnitsOnOrder) < myProd.ReorderLevel)
myProd.UnitsOnOrder = (short)(myProd.UnitsOnOrder + myProd.ReorderLevel);
}
xmlDoc.Save("Order_out.xml");
}
}