C#高级编程之处理XML-连载十七

时间:2010年04月12日 点击:317

23.8.3  读写DiffGram

DiffGram是包含数据在编辑对话前后的XML文档。它可以包含修改、增加和删除数据的任何组合。DiffGram可以用作审计跟踪或用于提交/回滚(commit/rollback)过程。目前的大多数DBMS系统都内置了DiffGram,但如果使用一个没有这些功能的DBMS,或者XML是数据库,且用户没有DBMS,就可以自己执行提交/重新运行过程。

下面的代码显示了如何创建一个DiffGram,以及如何从DiffGram:pwd 中创建一个DataSet(这段代码在ADOSample6文件夹中)

这段代码的起始部分您应很熟悉。定义和设置一个新的DataSet对象 ds,一个新的SqlConnection对象 conn和一个新的SqlDataAdapter对象 da。连接到数据库上,选择Products表中的所有行,创建一个新的DataTable,命名为products,把数据库中的数据加载到DataSet中:

private void button1_Click(object sender, System.EventArgs e)

{

   //new DataSet

   DataSet ds=new DataSet("XMLProducts");

   //Make connection and load products rows

   SqlConnection conn=new SqlConnection

               (@"server=GLYNNJ_CS\NetSDK;uid=sa;pwd=;database=northwind");

   SqlDataAdapter da=new SqlDataAdapter("SELECT * FROM products",conn);

   //fill the DataSet

   da.Fill(ds,"products");

   //edit first row

   ds.Tables["products"].Rows[0]["ProductName"]="NewProdName";

下面一部分代码完成了两个任务。首先,把第一行的ProductName列改为NewProdName。其次,在DataTable中创建一个新行,设置列值,最后把新的数据行添加到DataTable中:

   //add new row

   DataRow dr=ds.Tables["products"].NewRow();;

   dr["ProductId"]=100;

   dr["CategoryId"]=2;

   dr["Discontinued"]=false;

   dr["ProductName"]="This is the new product";

   dr["QuantityPerUnit"]=12;

   dr["ReorderLevel"]=1;

   dr["SupplierId"]=12;

   dr["UnitPrice"]=23;

   dr["UnitsInStock"]=5;

   dr["UnitsOnOrder"]=0;

   ds.Tables["products"].Rows.Add(dr);

这是代码中比较有意义的一部分。首先用WriteXmlSchema编写模式,这是非常重要的,因为没有模式,就不能读取DiffGram。带有XmlWriteMode.DiffGram参数的WriteXml创建了DiffGram。下一行代码接受我们进行的修改。在调用AcceptChanges前创建DiffGram也是很重要的,否则数据在修改前和修改后就不会有任何区别。

   //Write the Schema

   ds.WriteXmlSchema("..\\..\\..\\diffgram.xsd");

   //generate the DiffGram

   ds.WriteXml("..\\..\\..\\diffgram.xml",XmlWriteMode.DiffGram);

   ds.AcceptChanges();         

   //load data into grid

 

   dataGrid1.DataSource=ds;

   dataGrid1.DataMember="products";

 

   //new XmlDataDocument

   doc=new XmlDataDocument(ds);

   //load the productnames in the list

   XmlNodeList nodeLst=doc.SelectNodes("//ProductName");

   foreach(XmlNode nd in nodeLst)

      listBox1.Items.Add(nd.InnerXml);

}

为了把数据返回到DataSet中,执行下述代码:

      DataSet dsNew=new DataSet();

      dsNew.ReadXmlSchema("..\\..\\..\\diffgram.xsd");

      dsNew.XmlRead("..\\..\\..\\diffgram.xml",XmlReadMode.DiffGram);

在这个示例中,创建一个新的DataSet对象dsNew,调用ReadXmlSchema方法,根据模式信息创建一个新的DataTable。在本例中,就是products表的一个复制。现在可以读取DiffGram,该DiffGram不包含任何模式信息,所以在调用ReadXml方法前创建和准备好DataTable就是非常重要的。

下面是DiffGram的一个示例(diffgram.xml)

<?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">

  <XMLProducts>

    <products diffgr:id="products1" msdata:rowOrder="0"

              diffgr:hasChanges="modified">

      <ProductID>1</ProductID>

      <ProductName>NewProdName</ProductName>

      <SupplierID>1</SupplierID>

      <CategoryID>1</CategoryID>

      <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>

      <UnitPrice>18</UnitPrice>

      <UnitsInStock>39</UnitsInStock>

      <UnitsOnOrder>0</UnitsOnOrder>

      <ReorderLevel>10</ReorderLevel>

      <Discontinued>false</Discontinued>

    </products>

    ...

    <products diffgr:id="products78" msdata:rowOrder="77"

              diffgr:hasChanges="inserted">

      <ProductID>100</ProductID>

      <ProductName>This is the new product</ProductName>

      <SupplierID>12</SupplierID>

      <CategoryID>2</CategoryID>

      <QuantityPerUnit>12</QuantityPerUnit>

      <UnitPrice>23</UnitPrice>

      <UnitsInStock>5</UnitsInStock>

      <UnitsOnOrder>0</UnitsOnOrder>

      <ReorderLevel>1</ReorderLevel>

      <Discontinued>false</Discontinued>

    </products>

  </XMLProducts>

  <diffgr:before>

    <products diffgr:id="products1" msdata:rowOrder="0">

      <ProductID>1</ProductID>

      <ProductName>Chai</ProductName>

      <SupplierID>1</SupplierID>

      <CategoryID>1</CategoryID>

      <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>

      <UnitPrice>18</UnitPrice>

      <UnitsInStock>39</UnitsInStock>

      <UnitsOnOrder>0</UnitsOnOrder>

      <ReorderLevel>10</ReorderLevel>

      <Discontinued>false</Discontinued>

    </products>

  </diffgr:before>

</diffgr:diffgram>

注意每个DataTable行是如何重复的,每个<products>元素都有一个diffgr:id属性(为节省空间,只列出了第一个和最后一个<products>元素)Diffgrurn:schemas-microsoft-com:xml- diffgram-v1的命名空间前缀。对于修改和插入的行,ADO.NET增加了一个diffgr:hasChanges属性。在<XMLProducts>元素的后面还有一个ffgr:before>元素,它包含一个<products>元素,表示被修改的行以前的内容。显然,插入的行没有任何“以前”的值,所以在<diffgr:before>中没有元素。

在把DiffGram读入DataTable后,它就处于数据被修改之后,但在调用AcceptChanges之前的状态。此时可以通过调用RejectChanges方法撤销所进行的修改。通过查看DataRow.Item属性,以及它的参数DataRowVersion.Original DataRowVersion.Current,就可以确定DataTable在修改前后的值。

如果有一系列的DiffGram,能以合适的顺序重复应用它们是非常重要的。我们不想回退多次迭代所作的改变。但是如果使用的DBMS没有提供这些功能,可以使用DiffGram作为一种记录的格式,或用于审查。

智动软件

赞助商链接

热门内容

相关内容

联系我们

联系方式