[ Team LiB ]Recipe 5.10 Converting a DataSet to an ADO Recordset
Problem
You need to convert a DataSet to an ADO Recordset so that you can use it in a legacy
application.
Solution
You must persist the DataSet to XML, transform it to ADO Recordset schema, and load
it into an ADO Recordset using COM interop.
You'll need a reference to the Primary Interop Assembly (PIA) for ADO provided in the
file ADODB.DLL. Select adodb from the .NET tab in Visual Studio .NET's Add
Reference Dialog.
The sample uses one XML file:
Orders.xslt
The XSLT stylesheet used to transform the XML document output by the DataSet
into an ADO Recordset XML document.
The sample code contains one event handler and one method:
Go Button.Click
Converts the DataSet to an ADO Recordset using the following steps:
1. A shell XML document for the ADO Recordset is created.
2. A DataReader accesses the schema information for the data to convert
using the GetSchemaTable( ) method. This information is mapped to and
added to the ADO Recordset XML document.
3. The DataSet is loaded with data for a single DataTable. The XML
document for the DataSet is transformed and written into the ADO
Recordset XML document.
4. An ADO Recordset object is created and loaded with the ADO Recordset
XML document. This completes the conversion.
5. The ADO Recordset is loaded into a DataTable using the
OleDbDataAdapter. The default view for the table is bound to the data grid
<z:row>
<xsl:apply-templates select="@OrderID" />
<xsl:apply-templates select="@CustomerID" />
<xsl:apply-templates select="@EmployeeID" />
<xsl:apply-templates select="@OrderDate" />
<xsl:apply-templates select="@RequiredDate" />
<xsl:apply-templates select="@ShippedDate" />
<xsl:apply-templates select="@ShipVia" />
<xsl:apply-templates select="@Freight" />
<xsl:apply-templates select="@ShipName" />
<xsl:apply-templates select="@ShipAddress" />
<xsl:apply-templates select="@ShipCity" />
<xsl:apply-templates select="@ShipRegion" />
<xsl:apply-templates select="@ShipPostalCode" />
<xsl:apply-templates select="@ShipCountry" />
</z:row>
</xsl:template>
<xsl:template match="@OrderDate">
<xsl:attribute name="OrderDate">
<xsl:value-of select="wxh:GetShortTime(.)" />
</xsl:attribute>
</xsl:template>
<xsl:template match="@RequiredDate">
<xsl:attribute name="RequiredDate">
<xsl:value-of select="wxh:GetShortTime(.)" />
</xsl:attribute>
</xsl:template>
<xsl:template match="@ShippedDate">
<xsl:attribute name="ShippedDate">
<xsl:value-of select="wxh:GetShortTime(.)" />
String sqlText = "SELECT * FROM Orders";
// Create the connection.
SqlConnection conn = new SqlConnection(
ConfigurationSettings.AppSettings["Sql_ConnectString"]);
// Create the command to load all orders records.
SqlCommand cmd = new SqlCommand(sqlText, conn);
conn.Open( );
// Create a DataReader from the command.
SqlDataReader dr = cmd.ExecuteReader(
CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo);
// Create a table of the schema for the DataReader.
DataTable schemaTable = dr.GetSchemaTable( );
// Create an XML document.
XmlDocument xmlDoc = new XmlDocument( );
// Add ADO namespace and schema definition tags to the XML document.
String adoXml =
"<xml xmlns:s = 'uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882' " +
"xmlns:dt = 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882' " +
"xmlns:rs = 'urn:schemas-microsoft-com:rowset' " +
"xmlns:z = '#RowsetSchema'>" +
"<s:Schema id = 'RowsetSchema'>" +
"<s:ElementType name = 'row' content = 'eltOnly'>" +
"</s:ElementType>" +
"</s:Schema>" +
"</xml>";
xmlDoc.LoadXml(adoXml);
// Create a namespace manager for the XML document.
xa.Value = ((int)sr["ColumnOrdinal"] + 1).ToString( );
xe.SetAttributeNode(xa);
// Add attribute if null values are allowed in the column.
if((bool)sr["AllowDBNull"])
{
xa = xmlDoc.CreateAttribute("rs", "nullable",
"urn:schemas-microsoft-com:rowset");
xa.Value = sr["AllowDBNull"].ToString().ToLower( );
xe.SetAttributeNode(xa);
}
// Add 'writeunknown' attribute.
xa = xmlDoc.CreateAttribute("rs", "writeunknown",
"urn:schemas-microsoft-com:rowset");
xa.Value = "true";
xe.SetAttributeNode(xa);
// Create a 'datatype' element for the column within the
// 'AttributeType'.
XmlElement dataele = xmlDoc.CreateElement("s", "datatype",
"uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882");
String typeName, dbTypeName;
GetDataTypeInfo(sqlDbType, out typeName, out dbTypeName);
// Add a 'type' attribute specifying the data type.
xa = xmlDoc.CreateAttribute("dt", "type",
"uuid:C2F41010-65B3-11d1-A29F-00AA00C14882");
xa.Value = typeName;
dataele.SetAttributeNode(xa);
dataele.SetAttributeNode(xa);