Writing Data as XML

for RuBoard

As you learned yesterday , a DataSet can be serialized and deserialized to and from XML using the XmlSerializer class of the System.Xml.Serialization namespace. This process occurs when a DataSet is remoted across AppDomains or returned from an XML Web Service.

However, the DataSet also exposes the GetXml and WriteXml methods , which can be called directly to serialize the DataSet to XML. These methods function identically by writing out the contents of the DataSet using the Current row version that includes all modified and added rows and omits all deleted rows. For example, using the TitlesDs strongly typed DataSet defined in yesterday's lesson, the following code can be written to find a particular Sams title and lower its price by 10%:

 Dim books As TitlesDs Dim strXml As String Dim titleRow As TitlesDs.TitlesRow books = GetTitlesReviews("Sams") ' populate the DataSet titleRow = books.Titles.FindByISBN("06720083X") titleRow.Price = titleRow.Price * Convert.ToDecimal(0.90) strXml = books.GetXml() 

After the price has been lowered , the DataSet is written to XML and stored in a String variable using the GetXml method. The string can be written to a file or simply returned to the presentation tier . Listing 7.1 shows the relevant parts of the resulting XML.

Listing 7.1 Writing a DataSet as XML. This XML snippet shows the portions affected by the previous code snippet.
 <TitlesDs xmlns="http://www.computebooks.com/TitlesDs">   <Reviews>     <ReviewID>9cf97fcc-a6bb-4932-b427-213908427248</ReviewID>     <ISBN>06720083X </ISBN>     <ReviewText>Mediocre to the core</ReviewText>     <Stars>3</Stars>   </Reviews>   <Reviews>     <ReviewID>609a2f74-ec76-4e4e-835c-266f11a32021</ReviewID>     <ISBN>06720083X </ISBN>     <ReviewText>Clearly the greatest book ever written</ReviewText>     <Stars>5</Stars>   </Reviews>   <Reviews>     <ReviewID>5af1077d-77ef-4761-bf1a-6e31b905fa10</ReviewID>     <ISBN>06720083X </ISBN>     <ReviewText>It stunk really badly</ReviewText>     <Stars>0</Stars>   </Reviews>   <Titles>     <ISBN>06720083X </ISBN>     <Title>Pure Visual Basic: a code-intensive premium        reference/versions 5 &amp; 6</Title>     <Description>Great Book</Description>     <Author>Fox, Dan</Author>     <PubDate>1999-09-01T00:00:00.0000000-05:00</PubDate>     <Price>22.491</Price>     <Discount>9.5647</Dpiscount>     <BulkDiscount>10</BulkDiscount>     <BulkAmount>50</BulkAmount>     <CategoryName>Programming</CategoryName>     <PubName>Sams Publishing</PubName>   </Titles> </TitlesDs> 
graphics/analysis.gif

You'll notice from Listing 7.1 that because this book has reviews associated with it, the reviews are returned first, followed by the data for the book itself. This corresponds to the order in which the tables were added to the strongly typed DataSet in its InitClass method. The price of the book is now set to $22.49, down from the original price of $24.99. You'll also notice that the XML does not indicate that the price was modified using a DiffGram, even though AcceptChanges was not called on the row and it is in the Modified row state. You can also see that the namespace associated with the DataSet when it was created yesterday is represented in the root element.

The end result is that you can use the GetXml method when you simply want to quickly return the current contents of the DataSet as a String and are not concerned with tracking changes.

Although the WriteXml method returns the same XML by default, it is much more flexible in that it includes eight overloaded signatures that allow the XML to be written to a stream or its derived classes, the System.IO.TextWriter , an XmlWriter , or directly to a file specified with its path and name . The other four signatures support a second argument to customize the XML through the XmlWriteMode enumeration. The enumeration values include DiffGram , which will write the XML using the DiffGram grammar you learned about on Day 5, "Changing Data"; IgnoreSchema , which is the default; and WriteSchema , which also writes out the XSD for the DataSet . For example, to write the DiffGram for a DataSet to an in-memory stream, you can use the following code:

 Dim ms As New MemoryStream() books.GetChanges.WriteXml(ms, XmlWriteMode.DiffGram) 

In this case, the GetChanges method is first called on the DataSet to filter by the modified rows before writing the DiffGram to the MemoryStream using the WriteXml method.

Tip

Unless you actually want to write the XML to a String , using the WriteXml method is more efficient. This is because a string doesn't have to be created before the XML is written to a file or memory, as in this case.


Assuming that the same change to the price is still in effect, the resulting XML from the previous code snippet will contain the Titles element only, and not the Reviews elements, even though the reviews are linked via a DataRelation . To write out XML for just one book, you could create a new DataSet and copy into it the Titles row that was changed along with the related rows from the Reviews table. Listing 7.2 shows the code snippet necessary to do so with the strongly typed TitlesDs DataSet .

Listing 7.2 Copying from a DataSet . The WriteTitleXml function copies a row and its related rows to a new DataSet and returns the XML.
 Public Function WriteTitleXml(ByRef books As TitlesDs, _  ByRef titleRow As TitlesDs.TitlesRow) As String   Dim aBook As TitlesDs   Dim rowVals() As Object   Dim reviewRows() As TitlesDs.ReviewsRow   ' Make a new copy of the DataSet   aBook = CType(books.Clone(), TitlesDs)   ' Add the title row   rowVals = titleRow.ItemArray   aBook.Titles.Rows.Add(rowVals)   ' Add the reviews rows   reviewRows = titleRow.GetReviewsRows   Dim row As TitlesDs.ReviewsRow   For Each row In reviewRows     rowVals = row.ItemArray     aBook.Reviews.Rows.Add(rowVals)   Next   Return aBook.GetXml() End Function 
graphics/analysis.gif

You'll notice in Listing 7.2 that the original TitlesDs DataSet and the TitlesRow object are both passed into the method. The method then creates a new DataSet with the same structure using the Clone method. The ItemArray property is then used to extract an array of values for the TitlesRow , which is then added to the new DataSet using the Add method of the DataRowCollection . To retrieve the related rows from the Reviews table, the strongly typed DataSet exposes the GetReviewsRows method that uses the DataRelation to return an array of ReviewsRow objects. Each row is then added to the new DataSet using the Add method of the DataRowCollection for the Reviews table. Finally, the XML for the new DataSet is returned using the GetXml method.

Affecting the XML Format

The format of the XML shown in Listing 7.1 is controlled by the XSD generated when the DataSet was created in the graphical designer, as you saw yesterday. By default, the data for each DataTable appears consecutively, is placed in an element named with the table name, and each column is placed in a sub-element of the table. However, you can override these defaults either programmatically, using the properties of the objects in the DataSet , or graphically, in the designer. The former option will, of course, be useful when you are not using a strongly typed DataSet .

For example, assume that books is an instance of the TitlesDs DataSet . The following code snippet customizes the XML that will be generated when the GetXml or WriteXml method is called or when the DataSet is serialized to XML:

 books.Titles.Columns("ISBN").ColumnMapping = MappingType.Attribute books.Reviews.Columns("ReviewID").ColumnMapping = MappingType.Attribute books.Reviews.Columns("ISBN").ColumnMapping = MappingType.Attribute books.Relations(0).Nested = True books.Prefix = "cbks" 

Here you'll note that the ColumnMapping property can be used to specify how a column in the DataSet is represented using the MappingType enumeration. Other values include Element (the default), Hidden , and SimpleContent . In this case, the primary keys of the two tables, along with the ISBN column of the Reviews table, will be rendered as attributes.

Tip

The Hidden value of the MappingType attribute is useful for hiding columns in the table that are used only for relating tables within the DataSet and thus are auto-incremented. Basically, you would use Hidden with any column that you don't want a client of the DataSet to display to a user . However, marking a column as Hidden still allows it to be tracked when the DataSet is serialized with the XmlSerializer object. The hidden column is attached to the XML in a special attribute, called hiddenColumn , of the element for each row.


In addition, the Nested property of the DataRelation used to relate the two tables through their foreign key constraint is set to True so that rather than displaying the tables one after the other, the data from the child table ( Reviews ) is rendered as a child element of the particular parent element ( Titles ) to which it belongs. In this case, the ordinal value of the relation is used because there is only one in the collection. Finally, the Prefix attribute of the DataSet is set in order to associate a prefix with the XML namespace populated when the DataSet was created yesterday. The end result is XML like that shown in Listing 7.3.

Listing 7.3 Reformatted XML. This listing shows the XML of TitlesDs after the properties in the previous snippet are applied.
 <cbks:TitlesDs xmlns:cbks="http://www.computebooks.com/TitlesDs">   <Titles ISBN="06720083X " xmlns="http://www.computebooks.com/TitlesDs">     <Title>Pure Visual Basic: a code-intensive premium        reference/versions 5 &amp;6</Title>     <Description>Great Book</Description>     <Author>Fox, Dan</Author>     <PubDate>1999-09-01T00:00:00.0000000-05:00</PubDate>     <Price>22.491</Price>     <Discount>9.5647</Discount>     <BulkDiscount>10</BulkDiscount>     <BulkAmount>50</BulkAmount>     <CategoryName>Programming</CategoryName>     <PubName>Sams Publishing</PubName>     <Reviews ReviewID="9cf97fcc-a6bb-4932-b427-213908427248" ISBN="06720083X">       <ReviewText>Mediocre to the core</ReviewText>       <Stars>3</Stars>     </Reviews>     <Reviews ReviewID="609a2f74-ec76-4e4e-835c-266f11a32021" ISBN="06720083X">       <ReviewText>Clearly the greatest book ever written</ReviewText>       <Stars>5</Stars>     </Reviews>     <Reviews ReviewID="5af1077d-77ef-4761-bf1a-6e31b905fa10" ISBN="06720083X">       <ReviewText>It stunk really badly</ReviewText>       <Stars>0</Stars>     </Reviews>   </Titles> </cbks:TitlesDs> 

Of course, the ColumnMapping property can be set in the graphical designer by dropping down the list next to the column name and selecting A for attribute, for example, rather than leaving it as the default of E (element). Likewise, the Nested property can be set graphically by clicking on the relationship and changing the IsNested property in the properties window to True .

Tip

If you forget to set the ColumnMapping and Nested properties while designing a strongly typed DataSet , you can re- open the .xsd file by double- clicking on it and then setting the properties. Doing so will regenerate the code for the DataSet , visible by clicking on the Show All Files button on the toolbar. Alternatively, you can edit the generated code and add code like that shown in the previous snippet to the InitClass method of the derived DataSet class.


for RuBoard


Sams Teach Yourself Ado. Net in 21 Days
Sams Teach Yourself ADO.NET in 21 Days
ISBN: 0672323869
EAN: 2147483647
Year: 2002
Pages: 158
Authors: Dan Fox

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net