Creating an XML File That Shows Changes Made to a DataSet

Problem

When you use the GetXML( ) method of the DataSet , you may see only the current values in the DataSet . You want to get the original values and see which rows were added, edited, or deleted.

Solution

Create an XML DiffGram , which is a document that details the modifications made to a DataSet .

The sample code contains two event handlers and a single method:

Form.Load

Sets up the sample by loading the Categories table from Northwind into a DataSet and displays the DiffGram for the DataSet before modification.

Make Changes Button.Click

Deletes the first row, modifies the second row, inserts a row before the first row, and adds a row to the end of the Categories DataTable

DisplayDiffGram( )

This method outputs the DiffGram for the DataSet to both a file and to a textbox on the form.

The C# code is shown in Example 8-12.

Example 8-12. File: XmlDiffgramForm.cs

// Namespaces, variables, and constants using System; using System.Configuration; using System.Text; using System.IO; using System.Xml; using System.Xml.Schema; using System.Data; using System.Data.SqlClient; // Table name constants private const String CATEGORIES_TABLE = "Categories"; // Field name constants private const String CATEGORYNAME_FIELD = "CategoryName"; private const String XMLDIFFGRAMFILENAME = ConfigurationSettings.AppSettings["Temp_Directory"] + "CategoriesDiffgram.xml"; private DataSet ds; // . . . private void XmlDiffgramForm_Load(object sender, System.EventArgs e) { // Select fields from Categories table without the Picture BLOB. String sqlText = "SELECT CategoryID, CategoryName, Description " + "FROM Categories"; // Load the Categories table into the DataSet. SqlDataAdapter da = new SqlDataAdapter(sqlText, ConfigurationSettings.AppSettings["Sql_ConnectString"]); ds = new DataSet( ); da.Fill(ds, "Categories"); DisplayDiffGram( ); } private void makeChangesButton_Click(object sender, System.EventArgs e) { // Disable the make changes button. makeChangesButton.Enabled = false; DataTable dt = ds.Tables["Categories"]; // Delete the first row. dt.Rows[0].Delete( ); // Modify the second row. dt.Rows[1][CATEGORYNAME_FIELD] += "New "; // Insert a row. DataRow row = dt.NewRow( ); row.ItemArray = new object[] {0, "New Category0", "New Category0 Description"}; dt.Rows.InsertAt(row, 0); // Add a row. dt.Rows.Add(new object[] {9, "New Category9", "New Category9 Description"}); DisplayDiffGram( ); } private void DisplayDiffGram( ) { // Write the XML diffgram to a memory stream. MemoryStream ms = new MemoryStream( ); ds.WriteXml(ms, XmlWriteMode.DiffGram); // Write the memory stream to a file. FileStream fs = new FileStream(XMLDIFFGRAMFILENAME, FileMode.Create, FileAccess.Write); ms.WriteTo(fs); fs.Close( ); // Display the XML DiffGram. byte[] result = ms.ToArray( ); ms.Close( ); resultTextBox.Text = Encoding.UTF8.GetString(result,0,result.Length); }

Discussion

A DiffGram is an XML format used to specify both the original and current values for the contents of a DataSet . It does not include any schema information. The DiffGram is also the primary serialization format used by the .NET Framework to persist and serialize a DataSet . The DiffGram format is XML-based, making it platform and application independent. It is not, however, widely used or understood outside of Microsoft .NET applications.

The DiffGram format is divided into three sectionscurrent, original, and errorsas shown in the following example:

. . . . . . . . .

Here are descriptions of the three DiffGram sections:

The DataInstanceName is the name of the DataSet or DataTable . This block contains the current version of the data containing all modifications. Modified elements are identified with the diffgr:hasChanges="modified " annotation while new elements are identified with the diffgr:hasChanges="inserted " annotation. Deleted elements are not annotated, rather, they appear only in the < diffgr:before > section.

This section contains the original version of the elements that have been modified or deleted. Elements in this section are matched to elements in the section using the diffgr:id annotation with matching values.

This section contains error information for an element in the section. Elements in this section are matched to elements in the section using the diffgr:id annotation with matching values.

The example loads all Categories from Northwind into a DataTable called Categories in a DataSet . The first row is deleted, the second is modified, a row is inserted before the first row, and a row is added to the end of the DataTable . After these modifications, the DiffGram for the DataSet is:

diffgr:hasChanges="inserted"> 0 New Category0 New Category0 Description diffgr:hasChanges="modified"> 2 CondimentsNew Sweet and savory sauces, relishes, spreads, and seasonings 3 Confections Desserts, candies, and sweet breads 8 Seafood Seaweed and fish diffgr:hasChanges="inserted"> 9 New Category9 New Category9 Description 1 Beverages Soft drinks, coffees, teas, beers, and ales 2 Condiments Sweet and savory sauces, relishes, spreads, and seasonings

As expected, the DiffGram contains both the annotation indicating inserted and modified records. The section contains the original record for the deleted records with CategoryID =1 and the modified record with CategoryID =2.

As shown in the example, a DiffGram is written for the DataSet by specifying an XmlWriteMode of DiffGram when calling the WriteXml( ) method of the DataSet . The GetXml( ) method cannot be used to generate a DiffGram . A DataSet can be loaded from an XML DiffGram by specifying an XmlWriteMode of DiffGram when calling the ReadXml( ) method.

Категории