The
DataSet
is now ready to use just as if you had
created it procedurally. You can create new rows in each of its
tables, using the DataTable.NewRow( )
and
DataTable.Rows.Add( )
methods, as shown in Example 11-5.
using System; using System.Data; public class CreateData { public static void Main(string [ ] args) { DataSet dataSet = new DataSet( ); dataSet.ReadXmlSchema("Coupons.xsd"); DataTable couponsTable = dataSet.Tables["coupons"]; DataRow couponRow = couponsTable.NewRow( ); couponRow["coupon_code"] = "763FF"; couponRow["discount_amount"] = 0.5; couponRow["discount_type"] = DiscountType.Fixed; couponRow["expiration_date"] = new DateTime(2002,12,31); couponsTable.Rows.Add(couponRow); dataSet.WriteXml("Coupons.xml"); } }
Some important highlights of this program are listed below. First, a
new DataSet
instance is created, and its structure
is populated with the saved Coupons.xsd
schema:
DataSet dataSet = new DataSet( ); dataSet.ReadXmlSchema("Coupons.xsd");
Next, the “coupons” table is
retrieved using the
DataTableCollection
’s string
indexer:
DataTable couponsTable = dataSet.Tables["coupons"];
You
can only create a new row using the
DataTable
’s NewRow(
)
factory method. This is because the columns must be
populated according to the database schema stored in the
DataTable
. Note that the NewRow(
)
method does not actually add the new
DataRow
to the DataTable
; that
happens later:
DataRow couponRow = couponsTable.NewRow( );
Now you can access each column from the new
DataRow
and set its value:
couponRow["coupon_code"] = "763FF"; couponRow["discount_amount"] = 0.5; couponRow["discount_type"] = DiscountType.Fixed; couponRow["expiration_date"] = new DateTime(2002,12,31);
Now that
the DataRow
is fully populated with data,
it’s time to add it to the
DataTable
’s
DataRowCollection
. If some constraint or relation
was not satisfied at this point, a specific
DataException
is thrown, giving details as to what
constraint or relation was violated:
couponsTable.Rows.Add(couponRow);
Finally, the last line writes the entire DataSet
to an XML file:
dataSet.WriteXml("Coupons.xml");
The Coupons.xml
file generated by
the last line is shown in Example 11-6. You can see
that it’s a normal XML file, and it is valid
according to the schema in Coupons.xsd
.
<?xml version="1.0" standalone="yes"?> <AngusHardware> <coupons> <coupon_code>763FF</coupon_code> <discount_amount>0.5</discount_amount> <discount_type>1</discount_type> <expiration_date>2002-12-31T00:00:00.0000000-05:00</expiration_date> </coupons> </AngusHardware>
Remember,
you can always verify that any XML file is valid according to a DTD
or XML Schema with the XmlValidatingReader
:
XmlSchema schema = XmlSchema.Read( new FileStream("Coupons.xsd", FileMode.Open), null); XmlValidatingReader reader = new XmlValidatingReader( new XmlTextReader("Coupons.xml")); reader.Schemas.Add(schema); reader.ValidationType = ValidationType.Schema; while (reader.Read( )) { // this will throw an exception if invalid }
You can also create an XML file that
contains both the schema to define the DataSet
structure and the data to populate it. The DataSet.WriteXml(
)
method takes an additional optional parameter, an
XmlWriteMode
enumeration instance. The following
list shows its values and what effect they have:
DiffGram
The output file contains a
DiffGram
, which is an XML format that specifies
the differences between a DataSet
in memory and
the underlying database. I’ll talk more about the
DiffGram
later:
<?xml version="1.0" standalone="yes"?> <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"> <AngusHardware> <coupons diffgr:id="coupons1" msdata:rowOrder="0" diffgr:hasChanges="inserted"> ... </coupons> </AngusHardware> </diffgr:diffgram>
IgnoreSchema
Only the data are written to the output file. This is the default:
<?xml version="1.0" standalone="yes"?> <AngusHardware> <coupons> ... </coupons> </AngusHardware>
WriteSchema
The data and the schema are both written to the file:
<?xml version="1.0" standalone="yes"?> <AngusHardware> <xs:schema id="AngusHardware" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xs:element name="AngusHardware" msdata:IsDataSet="true"> ... </xs:element> </xs:schema> <coupons> ... </coupons> </AngusHardware>
Reading a
DataSet
’s structure and contents
is done in a similar fashion. The DataSet.ReadXml(
)
method takes an optional XmlReadMode
enumeration parameter. The following lists its possible values and
their effects:
Auto
If
the data is a DiffGram
, this is equivalent to
XmlReadMode.DiffGram
. If the
DataSet
already has a schema, or if the data has
an inline schema (that is, it was written with
XmlWriteMode.WriteSchema
), this is equivalent to
XmlReadMode.ReadSchema
. Otherwise, it is
equivalent to XmlReadMode.InferSchema
.
DiffGram
The DiffGram
is read and the changes are made to
the DataSet
in memory.
Fragment
The data is assumed to have come directly from a SQL Server
FOR XML
query.
IgnoreSchema
Any inline schema in the XML file is ignored, and the data are read
into the DataSet
’s existing
schema. Any data that do not fit the schema are discarded.
InferSchema
Any inline schema in the XML file is ignored. If the
DataSet
in memory already has a schema, the data
are loaded and any necessary tables and columns are added to the
schema. In case of a namespace clash between the
DataSet
’s schema and the inferred
schema, an exception is thrown.
ReadSchema
The inline schema in the XML file is read. If the
DataSet
in memory already has a schema, and new
tables from the XML file are added, but an exception is thrown if any
tables in the inline schema already exist in the
DataSet
.
18.191.195.111