Using DiffGrams for XML data modifications (XML and SQL part 9)

Friday Aug 22nd 2003 by Marcin Policht
Share:

Explore Diffgrams, a new feature introduced in SQLXML version 2.0 (and enhanced in the version 3.0). Learn how to modify relational data stored in a SQL database using Diffgrams.

In a previous article of this series, I described using bulk loading of XML data with scripting interfaces included in the SQLXML version 2.0 and later. Now, we are going to explore another feature introduced in SQLXML version 2.0 (and enhanced in the version 3.0) called Diffgrams.

In many aspects, Diffgrams are similar to the Updategrams described in an earlier article. They both can be used to modify relational data stored in a SQL database and they both accomplish this by comparing the "before" and "after" representation of this data presented in the XML format. However, there are also significant differences between the two, which deal with the following topics:

  • support for insert operations on tables with identity columns - even though it is available in both cases - is more complex in the case of diffgrams,
  • support for parameters - available only in updategrams,
  • presence of corresponding mapping schemas - in some (typically the simplest) cases, it is possible to use updategrams without corresponding mapping schemas, but schemas are always required when using diffgrams,
  • integration with ADO - available in both cases, however diffgrams provide much better integration with ADO.NET object model.

According to general syntactical rules, Diffgrams consist of five main elements:

  • <?xml version="1.0" ?> predicate
  • <diffgr:diffgram> element, which contains references to the namespaces and schemas used in the diffgram (including xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" namespace),
  • <DataInstance> element, which contains data values that will be used to apply changes to the database. If the change involves deletion of data, than this element is empty (but it has to be present).
  • <diffgr:before> element, which contains data values to which the change will be applied. If the change involves insertion of the data, then this element is omitted.
  • <diffgr:errors> element, which is intended as a container for errors that might have taken place during data modification. This element, however, is not used for SQL Server 2000 data modifications via SQLXML (so we will not be using it throughout our examples).

When modifying SQL Server 2000 data via SQLXML 2.0 or 3.0, diffgrams are stored on a Web server hosting the virtual directory representing the target database (just as XML templates are). This has two main implications in terms of IIS configuration:

  • "Allow template queries" on the Settings tab of a virtual directory properties dialog box needs to be enabled.
  • XML document representing diffgram, needs to reside in a folder associated with a virtual name of type template assigned to it.

Starting with the SQLXML 2.0, the management of the Web server is done using the IIS Virtual Directory Management tool. Even though the name of the tool has changed, its interface and most of functionality is very similar to the Configure SQL XML support in IIS tool included with SQL Server 2000. However, if your virtual directory was created using the original version of SQLXML, you will also need to upgrade it. This is done by launching IIS Virtual Directory Management tool, bringing up the virtual directory Properties dialog box, and clicking on "Upgrade to version 3" (or version 2 with SQLXML 2.0) command button located on identically labeled tab. This tab disappears once the upgrade is complete.

In addition, diffgrams require use of XDS mapping schemas. In the examples presented so far, we have been using XDR mapping schemas. As we pointed out in our previous article, creation of XDR schemas is simplified with the XML View Mapper utility. This freely downloadable GUI-based tool utilizes tables from a source database as the basis for schema definition. For example, XLM View Mapper produces the following schema for the Shippers table from the Northwind database:

<?xml  version="1.0"  encoding="windows-1252" ?>
<!-- Generated by XMLMapper.exe XDR Publisher -->
<Schema xmlns="urn:schemas-microsoft-com:xml-data" 
        xmlns:dt="urn:schemas-microsoft-com:datatypes" 
        xmlns:sql="urn:schemas-microsoft-com:xml-sql" > 
 <ElementType name="Shippers" 
              content="mixed" 
              order="many" > 
   <AttributeType name="ShipperID" 
                  dt:type="int" > 
   </AttributeType>
   <AttributeType name="CompanyName" 
                  dt:type="string" > 
   </AttributeType>
   <AttributeType name="Phone" 
                  dt:type="string" > 
   </AttributeType>
   <attribute type="ShipperID" 
              required="no" > 
   </attribute>
   <attribute type="CompanyName" 
              required="no" > 
   </attribute>
   <attribute type="Phone" 
              required="no" > 
   </attribute>
 </ElementType>
</Schema>

Once the XDR schema is available, you can convert it to XDS format by applying one of the following two methods:

  • by running CVTSCHEMA.EXE included with SQLXML 3.0 (the file resides in the Program Files\SQLXML 3.0\bin folder),
  • by running the XSD.EXE tool (the file resides in the Program Files\Microsoft.NET\SDK\v1.1\Bin folder), included with the Microsoft .NET Framework SDK, downloadable from the Microsoft Web site. Keep in mind that SDK takes a while to download (version 1.1 takes roughly 106 MB). One of many features offered by this tool is the ability to generate XSD schema (using various sources, including an XDR schema or an XML document).

After the conversion, we will end up with XSD schema in the format:

<?xml version="1.0" ?>
<xsd:schema xmlns:xsd=
	"http://www.w3.org/2001/XMLSchema" xmlns:dt="urn:schemas-microsoft-com:datatypes" 
xmlns:msch="urn:schemas-microsoft-com:mapping-schema">
  <xsd:element name="Shippers" msch:relation="Shippers"
 	type="Shippers_type"/>
  <xsd:complexType name="Shippers_type">
    <xsd:attribute name="ShipperID" type="xsd:integer"/>
    <xsd:attribute name="CompanyName" type="xsd:string"/>
    <xsd:attribute name="Phone" type="xsd:string"/>
  </xsd:complexType>
</xsd:schema>


There are two situations to consider when inserting rows into the Shippers table, which contains identity column (ShipperID):



  • value in the identity column should be assigned using the next available value (and value specified in the diffgram should be ignored). This is accomplished by setting the identity annotation with the value of ignore (as defined in the "urn:schemas-microsoft-com:mapping-schema" namespace)

  • Value in the identity column should be assigned according to the data value in the diffgram. This is accomplished by setting the identity annotation with the value of useValue (as defined in the "urn:schemas-microsoft-com:mapping-schema" namespace)


For example, to insert the record into the Shippers table of Northwind database and set the value of the identity column according to the value provided in the diffgram (the second case), our schema would take the form:



<?xml version="1.0" ?>
<xsd:schema xmlns:xsd=
	"http://www.w3.org/2001/XMLSchema" xmlns:dt=
	  "urn:schemas-microsoft-com:datatypes" 
xmlns:msch="urn:schemas-microsoft-com:mapping-schema">
  <xsd:element name="Shippers" msch:relation="Shippers"
 	type="Shippers_type"/>
  <xsd:complexType name="Shippers_type">
    <xsd:attribute name="ShipperID" type="xsd:integer"
		msch:identity="useValue"/>
    <xsd:attribute name="CompanyName" type="xsd:string"/>
    <xsd:attribute name="Phone" type="xsd:string"/>
  </xsd:complexType>
</xsd:schema>

With the XSD template defined as above, you would create a diffgram in the following format:

>ShippersList xmlns:sql="urn:schemas-microsoft-com:xml-sql" 
          sql:mapping-schema="ShippersID.xsd"<
  >diffgr:diffgram 
     xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" 
     xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"<
  >DataInstance<
       >Shippers diffgr:id="Shipper4" msdata:rowOrder="0"  
                 diffgr:hasChanges="inserted"
		 ShipperID="4" 
 		 CompanyName="Speedy Gonzalez"
        	 Phone="(503) 555-9934"/<
    >/DataInstance<
  >/diffgr:diffgram<
>/ShippersList<

The diffgram above assumes that the XSD schema created previously has been saved as Shippers.xsd and stored in the same folder as the diffgram itself. Save it as InsertShippers.xml.

In order to examine how Diffgrams operate, use the following sequence of steps:

  • Create a physical folder that will host a virtual directory that will be created in the next step. For the sake of an example, let's assume that the folder will be C:\Inetpub\wwwroot\Northwind.
  • Create virtual directory Northwind using IIS Virtual Directory Management for SQLXML 3.0, with the folder created in the previous step as the local path. Make sure that "Allow template queries" is selected on the Settings tab.
  • Create a subfolder in the folder hosting the Northwind virtual directory called Diffgrams (this name is arbitrary),
  • Create a new virtual name (we will call it Diffgrams, but you can choose any name) of the template type and point it to C:\Inetpub\wwwroot\Northwind\Diffgrams,
  • Copy the Shippers.xsd and InsertShippers.xml file to the Diffgrams subfolder.
  • Finally, type
    http://localhost/ServerName/Diffgrams/InsertShippers.xml
    in the URL box of the browser, where ServerName is the name of the Web server hosting the virtual directory. Providing the operation was successful, you will see the following being displayed:
    <ShippersList xmlns:sql="urn:schemas-microsoft-com:xml-sql" />

Now let's demonstrate how to delete data from a SQL Server 2000 database with Diffgrams. Our example will remove the same row that was just inserted. Since the schema has not changed, we simply need to create a new XML document that will contain an empty <DataInstance> element and appropriate values in the <diffgr:before> element. This will take the following form:

<ShippersList xmlns:sql="urn:schemas-microsoft-com:xml-sql" 
          sql:mapping-schema="Shippers.xsd">
  <diffgr:diffgram 
     xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" 
     xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
  <DataInstance />
  <diffgr:before>
       <Shippers diffgr:id="Shipper4"  
		 ShipperID="4" 
 		 CompanyName="Speedy Gonzalez"
        	 Phone="(503) 555-9934"/>
  </diffgr:before>
  </diffgr:diffgram>
</ShippersList>

Note that, with existing schema, you need to provide values for all columns of the row to be deleted. If you omit any of them, they will be substituted with NULL value, which, in our case, would not produce the desired results (since the row for ShipperID of 4 does not have a NULL value in any of its columns, the row would not get deleted). If your intention is to delete rows based on the value of ShipperID only, you will need to modify the Shippers.XSD schema so it includes only this single attribute.

Even though diffgrams seem to be more cumbersome to use than updategrams, it is likely that you will run across them sooner or later, since they are the preferred method of dealing with SQL server database modifications with ADO.NET. You can use it as an alternative to updategrams, keeping in mind the pros and cons of each.

In the next article, I will present another feature included in SQLXML 2.0 and 3.0, called client-side XML processing.

» See All Articles by Columnist Marcin Policht

Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved