A DiffGram is an XML format that identifies current and original versions of data elements. The DataSet uses the DiffGram format to load and persist its contents, and to serialize its contents for transport across a network connection. When a DataSet is written as a DiffGram, it populates the DiffGram with all the necessary information to accurately recreate the contents, though not the schema, of the DataSet, including column values from both the Original and Current row versions, row error information, and row order.

When sending and retrieving a DataSet from an XML Web service, the DiffGram format is implicitly used. Additionally, when loading the contents of a DataSet from XML using the ReadXml method, or when writing the contents of a DataSet in XML using the WriteXml method, you can specify that the contents be read or written as a DiffGram. For more information, see Loading a DataSet from XML and Writing DataSet Contents as XML Data.

While the DiffGram format is primarily used by the .NET Framework as a serialization format for the contents of a DataSet, you can also use DiffGrams to modify data in tables in a Microsoft SQL Server database.

A Diffgram is generated by writing the contents of all tables to a <diffgram> element.

To generate a Diffgram

  1. Generate a list of Root tables (that is, tables without any parent).

  2. For each table and its descendants in the list, write out the current version of all rows in the first Diffgram section.

  3. For each table in the DataSet, write out the original version of all rows, if any, in the <before> section of the Diffgram.

  4. For rows that have errors, write the error content in the <errors> section of the Diffgram.

A Diffgram is processed in order from beginning of the XML file to the end.

To process a Diffgram

  1. Process the first section of the Diffgram that contains the current version of the rows.

  2. Process the second or the <before> section that contains the original row version of modified and deleted rows.


    If a row is marked deleted, the delete operation can delete the row's descendants as well, depending on the Cascade property of the current DataSet.

  3. Process the <errors> section. Set the error information for the specified row and column for each item in this section.


If you set the XmlWriteMode to Diffgram, the content of the target DataSet and the original DataSet may differ.

DiffGram Format

The DiffGram format is divided into three sections: the current data, the original (or "before") data, and an errors section, as shown in the following example.

<?xml version="1.0"?>  

The DiffGram format consists of the following blocks of data:

< DataInstance >
The name of this element, DataInstance, is used for explanation purposes in this documentation. A DataInstance element represents a DataSet or a row of a DataTable. Instead of DataInstance, the element would contain the name of the DataSet or DataTable. This block of the DiffGram format contains the current data, whether it has been modified or not. An element, or row, that has been modified is identified with the diffgr:hasChanges annotation.

This block of the DiffGram format contains the original version of a row. Elements in this block are matched to elements in the DataInstance block using the diffgr:id annotation.

This block of the DiffGram format contains error information for a particular row in the DataInstance block. Elements in this block are matched to elements in the DataInstance block using the diffgr:id annotation.

DiffGram Annotations

DiffGrams use several annotations to relate elements from the different DiffGram blocks that represent different row versions or error information in the DataSet.

The following table describes the DiffGram annotations that are defined in the DiffGram namespace urn:schemas-microsoft-com:xml-diffgram-v1.

Annotation Description
id Used to pair the elements in the <diffgr:before> and <diffgr:errors> blocks to elements in the < DataInstance > block. Values with the diffgr:id annotation are in the form [TableName][RowIdentifier]. For example: <Customers diffgr:id="Customers1">.
parentId Identifies which element from the < DataInstance > block is the parent element of the current element. Values with the diffgr:parentId annotation are in the form [TableName][RowIdentifier]. For example: <Orders diffgr:parentId="Customers1">.
hasChanges Identifies a row in the < DataInstance > block as modified. The hasChanges annotation can have one of the following two values:

Identifies an Added row.

Identifies a Modified row that contains an Original row version in the <diffgr:before> block. Note that Deleted rows will have an Original row version in the <diffgr:before> block, but there will be no annotated element in the < DataInstance > block.
hasErrors Identifies a row in the < DataInstance > block with a RowError. The error element is placed in the <diffgr:errors> block.
Error Contains the text of the RowError for a particular element in the <diffgr:errors> block.

The DataSet includes additional annotations when reading or writing its contents as a DiffGram. The following table describes these additional annotations, which are defined in the namespace urn:schemas-microsoft-com:xml-msdata.

Annotation Description
RowOrder Preserves the row order of the original data and identifies the index of a row in a particular DataTable.
Hidden Identifies a column as having a ColumnMapping property set to MappingType.Hidden. The attribute is written in the format msdata:hidden [ColumnName]="value". For example: <Customers diffgr:id="Customers1" msdata:hiddenContactTitle="Owner">.

Note that hidden columns are only written as a DiffGram attribute if they contain data. Otherwise, they are ignored.

Sample DiffGram

An example of the DiffGram format is shown below. This example shows the result of an update to a row in a table before the changes have been committed. The row with a CustomerID of "ALFKI" has been modified, but not updated. As a result, there is a Current row with a diffgr:id of "Customers1" in the < DataInstance > block, and an Original row with a diffgr:id of "Customers1" in the <diffgr:before> block. The row with a CustomerID of "ANATR" includes a RowError, so it is annotated with diffgr:hasErrors="true" and there is a related element in the <diffgr:errors> block.

<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">  
    <Customers diffgr:id="Customers1" msdata:rowOrder="0" diffgr:hasChanges="modified">  
      <CompanyName>New Company</CompanyName>  
    <Customers diffgr:id="Customers2" msdata:rowOrder="1" diffgram:hasErrors="true">  
      <CompanyName>Ana Trujillo Emparedados y Helados</CompanyName>  
    <Customers diffgr:id="Customers3" msdata:rowOrder="2">  
      <CompanyName>Antonio Moreno Taquera</CompanyName>  
    <Customers diffgr:id="Customers4" msdata:rowOrder="3">  
      <CompanyName>Around the Horn</CompanyName>  
    <Customers diffgr:id="Customers1" msdata:rowOrder="0">  
      <CompanyName>Alfreds Futterkiste</CompanyName>  
    <Customers diffgr:id="Customers2" diffgr:Error="An optimistic concurrency violation has occurred for this row."/>  

See also