Книга: C# для профессионалов. Том II

Запись и чтение DiffGram

Запись и чтение DiffGram

DiffGram является документом XML, который содержит данные до и после сеанса редактирования, включающего любую комбинацию изменений данных, добавлений и удалений. DiffGram может использоваться как аудиторский журнал или для процесса подтверждения/отката. Большинство систем DBMS сегодня имеют такое встроенное средство. Но если придется работать с DBMS, которая не имеет таких свойств или если хранилищем данных является XML и отсутствует DBMS, то можно будет самостоятельно реализовать свойства подтверждения/отката.

Далее представлен код, показывающий, как DiffGram создается и как DataSet можно создать из DiffGram:pwd (он находится в папке ADOSample6). Начальная часть этого кода должна быть уже знакома. Мы определяем и задаем новый объект DataSet, ds, новый объект SqlConnection, conn и новый объект SqlDataAdapter, da. Мы соединяемся с базой данных, выбираем все строки из таблицы Products, создаем новый объект DataTable с именем products и загружаем данные из базы данных в DataSet:

private void button1_Click(object sender, System.EventArgs e) {
 // новый объект DataSet
 DataSet ds=new DataSet("XMLProducts");
 // Сделать соединение и загрузить строки продуктов
 SqlConnection conn=
  new SqlConnection(@"server=GLYNNJ_CSNetSDK;uid=sa;pwd=;database=northwind");
 SqlDataAdapter da=new SqlDataAdapter("select * from products", conn);
 // заполнить DataSet
 da.Fill(ds, "products");
 // редактируем первую строку
 ds.Tables["products"].Rows[0]["ProductName"] = "NewProdName";

В следующем разделе мы сделаем следующие преобразования. Во-первых, изменим столбец ProductName в первой строке на NewProdName. Во-вторых, создадим новую строку в DataTable, задавая значения столбцов и добавляя в конце новую строку данных в DataTable.

 // добавить новую строку
 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;
 Tables["products"].Rows.Add(dr);

Это интересная часть кода. Прежде всего записывается схема с помощью WriteXmlSchema. Это важно, так как нельзя будет заново считать в DiffGram без схемы. WriteXml с переданным в него параметром XmlWriteMode.DiffGram создает в действительности DiffGram. Следующая строка принимает сделанные изменения. Важно то, что DiffGram создается до вызова AcceptChanges, иначе не будет никакого различия между состоянием до того и после.

// записать схему
ds.WriteXmlSchema("......diffgram.xsd");
// создать DiffGram
ds.WriteXml("......diffgram.xml", XmlWriteMode.DiffGram);
ds.AcceptChanges();
// загрузить данные в сетку
dataGrid1.DataSource=ds;
dataGrid1.DataMember="products";
// новый объект XmlDataDocument
doc=new XmlDataDocument(ds);
// загрузить имена продуктов в список
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 на основе информации схемы. В данном случае он будет клоном DataTable продуктов. Теперь можно считать в DiffGram. DiffGram не содержит информации о схеме, поэтому важно, чтобы объект DataTable был создан и готов к использованию до вызова метода ReadXml. Вот образец того, как выглядит 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:hasChanged="modified">
    <ProductID>1</ProduсtID>
    <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="products2" msdata:rowOrder="1">
    <ProductID>2</ProductID>
    <ProduсtName>Chang</ProductName>
    <SupplierID>1</SupplierID>
    <CategoryID>1</CategoryID>
    <QuantityPerUnit>24 - 12 oz bottles</QuantityPerUnit>
    <UnitPrice>19</UnitPrice>
    <UnitsInStock>17</UnitsInStock>
    <UnitsOnOrder>40</UnitsOnOrder>
    <ReorderLevel>25</ReorderLevel>
    <Discontinued>false</Discontinued>
   </products>

   <products diffgr:id="products78" msdata:rowOrder="77" diffgr:hasChanges="inserted">
    <ProductID>100</ProductID>
    <ProductName>This is a 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 bugs </QuantityPerUnit>
    <UnitPrice>18</UnitPrice>
    <UnitsInStock>39</UnitsInStock>
    <UnitsOnOrder>0</UnitsOnOrder>
    <ReorderLevel>10</ReorderLevel>
    <Discontinued>false</Discontinued>
   </products>
  </diffgr:before>
</diffgr:diffgram>

Заметим, каким образом повторяется каждая строка DataTable, и что существует атрибут diffgr:id для каждого элемента <products>. diffgr является префиксом пространства имен для urn:schemas-microsoft-com:xml-diffgram-v1. Для модифицированной строки и для вставленной строки ADO.NET добавляет атрибут diffgr:hasChanges. Здесь есть также элемент <diffgr:before> после элемента <XMLProducts>, который содержит элемент <products>, указывающий на предыдущее содержание всех модифицированных строк. Для добавленной строки не существует "before", поэтому здесь отсутствует элемент <diffgr:before>, однако он присутствует для модифицированной строки.

После того как DiffGram считан в DataTable, он оказывается в состоянии, в котором он был бы после выполнения изменений в данных перед вызовом AcceptChanges. В этом месте можно на самом деле откатить изменения, вызывая метод RejectChanges. Проверяя свойство DataRow.Item и передавая либо DataRowVersion.Original, либо DataRowVersion.Current, можно увидеть значения в DataTable перед и после изменений.

Оглавление книги


Генерация: 2.767. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз