DA20 - Data Abstract Adapters

 
DA20 - Data Abstract Adapters
本文说明什么是 Data Abstract Adapters , 如何运行 , 以及 XML Adapter 可用于与 .Net, Java 或其他支持 XML 操作的语言生成的系统交换数据的 新特性 .
Data Adapters
Data Adapters 是一个 Data Abstract 架构中的支持数据特定格式化并在网络传输和本地存储的组件 . 此外 , data adapters 也可以同样处理数据表的 Delta 信息 .
Data Abstract 提供了两个 Data Adapter:
  • TDABINAdapter: 将数据集数据转换为适当的二进制格式.这个Adapter是最快的一个也是在不需要考虑与外部系统互用时的首选.
  • TDAXMLAdapter: 将数据集数据转换为XML文档. 这个XML格式是Data Abstract特有的,但是这个组件应用XSLT 轻松转化为其他格式
虽然你可以使用 data adapter 做其他任务 ( 例如使用 XML Adapter 将数据集数据转化为 HTML 页面 ), 但是它们通常用于客户端的 Data Tables 以及服务端的远程服务 ( ServiceAdapter 属性 ). Data Tables DARemoteServices 需要 data adapters 指定如何序列化或反序列化数据 .
所有的 data adapters 继承于 TDADataAdapter (uDADataTable.pas 单元 ).
TDADataAdapter 提供了所有写入或读取 Adapter 的必要方法 . 下面的代码展示了如何使用 XML Data Adapter 序列化两个查询 (Schema 中预先定义的 Customers Orders ) 的数据 :
var
  conn : IDAConnection;
 orders, customers : IDADataset;
 xmlstream : TMemoryStream;
begin
xmlstream := TMemoryStream.Create;
try
  // Opens a database connections and queries for the two tables
  conn := ConnectionManager.NewConnection( 'ADO' );
 customers := Schema.NewDataset(conn, ds_Customers);
 orders := Schema.NewDataset(conn, ds_Orders);
  // Writes the data into the stream by using the XML Adapter
  XMLAdapter.WriteXSLT := NIL; // In case there's one set
  XMLAdapter.Initialize(xmlstream, aiWrite);
  XMLAdapter.WriteDataset(customers, [woSchema, woRows]);
 XMLAdapter.WriteDataset(orders, [woSchema, woRows]);
 XMLAdapter.Finalize;
 [..]
执行这段代码后 , xmlstream 流中将包含如下格式的 XML 文档 :
< XMLData >< Schema >< Datasets >< Customers >< Fields >
< Field Alignment =" taLeftJustify " BlobType =" dabtUnknown "
  BusinessRulesID ="" Calculated =" False " CustomAttributes =" 10370684 "
  DataType =" datAutoInc " DefaultValue ="" Description =""
  DictionaryEntry ="" DisplayFormat ="" DisplayLabel =" CustomerIdx "
  DisplayWidth =" 0 " EditFormat ="" EditMask ="" GeneratorName =""
  InPrimaryKey =" True " KeyFields ="" LogChanges =" True " Lookup =" False "
  LookupCache =" False " LookupKeyFields ="" LookupResultField =""
  LookupSource =" 0 " Name =" CustomerIdx " ReadOnly =" False "
  RegExpression ="" Required =" True " ServerAutoRefresh =" False " Size =" 0 "
  Visible =" True "/>
< Field Alignment =" taLeftJustify " BlobType =" dabtUnknown "
  BusinessRulesID ="" Calculated =" False " CustomAttributes =" 10370916 "
  DataType =" datString " DefaultValue ="" Description =""
  DictionaryEntry ="" DisplayFormat ="" DisplayLabel =" FirstName "
  DisplayWidth =" 0 " EditFormat ="" EditMask ="" GeneratorName =""
  InPrimaryKey =" False " KeyFields ="" LogChanges =" True " Lookup =" False "
  LookupCache =" False " LookupKeyFields ="" LookupResultField =""
  LookupSource =" 0 " Name =" FirstName " ReadOnly =" False " RegExpression =""
  Required =" True " ServerAutoRefresh =" False " Size =" 20 " Visible =" True "/>
[..]
</ Fields ></ Customers >
< Orders >< Fields >
[..]
< Field Alignment =" taLeftJustify " BlobType =" dabtUnknown "
  BusinessRulesID ="" Calculated =" False " CustomAttributes =" 10407460 "
  DataType =" datDateTime " DefaultValue ="" Description =""
  DictionaryEntry ="" DisplayFormat ="" DisplayLabel =" InsertDate "
  DisplayWidth =" 0 " EditFormat ="" EditMask ="" GeneratorName =""
  InPrimaryKey =" False " KeyFields ="" LogChanges =" True " Lookup =" False "
  LookupCache =" False " LookupKeyFields ="" LookupResultField =""
  LookupSource =" 0 " Name =" InsertDate " ReadOnly =" False " RegExpression =""
  Required =" True " ServerAutoRefresh =" False " Size =" 0 " Visible =" True "/>
< Field Alignment =" taLeftJustify " BlobType =" dabtUnknown "
  BusinessRulesID ="" Calculated =" False " CustomAttributes =" 10407692 "
  DataType =" datDateTime " DefaultValue ="" Description =""
  DictionaryEntry ="" DisplayFormat ="" DisplayLabel =" ShipDate "
  DisplayWidth =" 0 " EditFormat ="" EditMask ="" GeneratorName =""
  InPrimaryKey =" False " KeyFields ="" LogChanges =" True " Lookup =" False "
  LookupCache =" False " LookupKeyFields ="" LookupResultField =""
  LookupSource =" 0 " Name =" ShipDate " ReadOnly =" False " RegExpression =""
  Required =" False " ServerAutoRefresh =" False " Size =" 0 " Visible =" True "/>
[..]
</ Fields ></ Orders ></ Datasets ></ Schema >
< Datasets >< Customers >
< Row CustomerIdx =" 1 " FirstName =" Wilton " LastName =" Forster "
  Address1 =" 1371 Inventing Street " City =" Jefferson " State =" SC "
  Zip =" 72680 " Phone1 =" (701) 618-2856 " Email =" [email protected] "/>
< Row CustomerIdx =" 2 " FirstName =" Doyle " MiddleName =" Barry "
  LastName =" Acherman " Address1 =" 3322 Widened Street " City =" Mcallen "
  State =" TX " Zip =" 64448 " Phone1 =" (653) 818-8635 " Fax =" (364) 702-7820 "
  Email =" [email protected] "/>
< Row CustomerIdx =" 3 " FirstName =" Fanchon " LastName =" Kuehler "
  Address1 =" 6767 Sleepily Street " City =" Killeen " State =" MT " Zip =" 18460 "
  Phone1 =" (742) 613-6096 " Phone2 =" (459) 475-9756 "
  Email =" [email protected] "/>
[..]
</ Customers >
< Orders >
[..]
< Row OrderIdx =" 14466 " CustomerIdx =" 6 " ShipperIdx =" 3 "
  TotalPrice =" 47555.93 " ShippingCost =" 66.98 " InsertedBy =" 10 "
  InsertDate =" 11/5/2003 11:20:27 AM " ShipDate =" 11/8/2003 11:20:27 AM "/>
< Row OrderIdx =" 14559 " CustomerIdx =" 3 " ShipperIdx =" 4 "
  TotalPrice =" 39819.58 " ShippingCost =" 40.51 " InsertedBy =" 10 "
  InsertDate =" 9/17/2003 5:10:17 AM " ShipDate =" 9/21/2003 5:10:17 AM "/>
< Row OrderIdx =" 14566 " CustomerIdx =" 4 " ShipperIdx =" 5 "
  TotalPrice =" 94003 " ShippingCost =" 67.94 " InsertedBy =" 5 "
  InsertDate =" 3/3/2004 5:05:27 PM " ShipDate =" 3/8/2004 5:05:27 PM "/>
< Row OrderIdx =" 14725 " CustomerIdx =" 9 " ShipperIdx =" 3 "
  TotalPrice =" 36270.27 " ShippingCost =" 60.77 " InsertedBy =" 7 "
  InsertDate =" 7/22/2003 6:51:48 PM " ShipDate =" 7/25/2003 6:51:48 PM "/>
</ Orders ></ Datasets ></ XMLData >
这里只显示其中部分条目的信息 , 完全的文件 (DatasetSample.xml) 请见本文上面的代码连接 .
如果你要从这个 XML 文件的内容中重新获取这两个数据集 , 代码如下 :
// Loads the data in the data tables
  XMLAdapter.Initialize(xmlstream, aiRead);
 XMLAdapter.ReadDataset(ds_Orders, dtOrders, TRUE);
 XMLAdapter.ReadDataset(ds_Customers, dtCustomers, TRUE);
 XMLAdapter.Finalize;
如果你需要保存这两个数据表的变更 Delta, 你必须使用 WriteDelta ReadDelta 方法 . 例如 :
var xmlstream : TMemoryStream;
 [..]
begin
  [..]
 xmlstream := TMemoryStream.Create;
 try
    // Generates some test updates (ask confirmation first)
    CreateTestUpdates;
    // Erases the XSLT in case there's one set
    XMLAdapter.WriteXSLT := NIL; // In case there's one set
    // Writes the data table deltas into the stream
    // by using the XML Adapter
    XMLAdapter.Initialize(xmlstream, aiWrite);
    XMLAdapter.WriteDelta(dtCustomers);
    XMLAdapter.WriteDelta(dtOrders);
    XMLAdapter.Finalize;
这段代码执行后 ,xmlstream 中将包含如下格式的 XML 文档 :
< XMLData >< Schema >< Deltas >< Customers >< LoggedFields >
 < Field Name =" CustomerIdx " DataType =" datAutoInc "/>
 < Field Name =" FirstName " DataType =" datString "/>
 < Field Name =" MiddleName " DataType =" datString "/>
[..]
</ LoggedFields >
< KeyFields >< Field Name =" CustomerIdx "/></ KeyFields ></ Customers >
< Orders >< LoggedFields >
 < Field Name =" OrderIdx " DataType =" datAutoInc "/>
 < Field Name =" CustomerIdx " DataType =" datInteger "/>
[..]
</ LoggedFields >
< KeyFields >< Field Name =" OrderIdx "/></ KeyFields >
</ Orders ></ Deltas ></ Schema >
< Deltas >
< Customers >
< Row >< RecID > 10 </ RecID >< ChangeType > ctDelete </ ChangeType >
 < Status > csPending </ Status >< Message ></ Message >< OldValues
  CustomerIdx =" 10 " FirstName =" Hester " MiddleName ="" LastName =" Rivera "
  Address1 =" 11275 Prematurity Lane " Address2 ="" City =" Turner " State =" IL "
  Zip =" 40587 " Phone1 =" (717) 345-9144 " Phone2 ="" Fax =""
  Email =" [email protected] " CreditCard =" 6482554456718807 "/>
 < NewValues CustomerIdx ="" FirstName ="" MiddleName ="" LastName =""
  Address1 ="" Address2 ="" City ="" State ="" Zip ="" Phone1 ="" Phone2 =""
  Fax ="" Email ="" CreditCard =""/></ Row >
< Row >< RecID > 11 </ RecID >< ChangeType > ctInsert </ ChangeType >
 < Status > csPending </ Status >< Message ></ Message >< OldValues
  CustomerIdx ="" FirstName ="" MiddleName ="" LastName ="" Address1 =""
  Address2 ="" City ="" State ="" Zip ="" Phone1 ="" Phone2 ="" Fax =""
  Email ="" CreditCard =""/>< NewValues CustomerIdx =" -1 " FirstName =" John "
  MiddleName ="" LastName =" Smith " Address1 =" 202 North Lake Drive "
  Address2 ="" City =" Barrington " State =" IL " Zip =" 60010 "
  Phone1 =" 847 389 2112 " Phone2 ="" Fax ="" Email =" [email protected] "
  CreditCard =" 3333-2222-1111-2 "/></ Row >
[..]
</ Customers >
< Orders >
< Row >< RecID > 113 </ RecID >< ChangeType > ctDelete </ ChangeType >
 < Status > csPending </ Status >< Message ></ Message >< OldValues
  OrderIdx =" 12078 " CustomerIdx =" 8 " ShipperIdx =" 3 "
  TotalPrice =" 30925.13 " ShippingCost =" 64.07 " InsertedBy =" 9 "
  InsertDate =" 7/17/2003 9:34:56 AM " ShipDate =" 7/20/2003 9:34:56 AM "/>
 < NewValues OrderIdx ="" CustomerIdx ="" ShipperIdx ="" TotalPrice =""
  ShippingCost ="" InsertedBy ="" InsertDate ="" ShipDate =""/></ Row >
< Row >< RecID > 114 </ RecID >< ChangeType > ctDelete </ ChangeType >
 < Status > csPending </ Status >< Message ></ Message >
 < OldValues OrderIdx =" 12552 " CustomerIdx =" 8 " ShipperIdx =" 4 "
  TotalPrice =" 78890.59 " ShippingCost =" 50.37 " InsertedBy =" 7 "
  InsertDate =" 11/5/2003 6:45:39 AM " ShipDate =" 11/9/2003 6:45:39 AM "/>
 < NewValues OrderIdx ="" CustomerIdx ="" ShipperIdx ="" TotalPrice =""
  ShippingCost ="" InsertedBy ="" InsertDate ="" ShipDate =""/></ Row >
[..]
</ Orders ></ Deltas ></ XMLData >
如上面的 , 完全文件 (DeltaSample.xml) 可见本文上面的源码连接 .
为了从这个 XML 文档中重新生成两个初始的 Delta, 必须写如下代码 :
var
  xmlstream : TMemoryStream;
 customersdelta,
 ordersdelta : IDADelta;
begin
  [..]
  // Reads the deltas from the stream
  customersdelta := NewDelta(ds_Customers);
 ordersdelta := NewDelta(ds_Orders);
 xmlstream.Position := 0 ;
 XMLAdapter.Initialize(xmlstream, aiRead);
 XMLAdapter.ReadDelta( 'Customers' , customersdelta);
 XMLAdapter.ReadDelta( 'Orders' , ordersdelta);
 XMLAdapter.Finalize;
可见 Data Abstract data adapter 可以向流中写入多个数据集或 Delta 以便于在客户端与服务端交换数据时节省网络请求 . 上面这些代码可以看作与 XML adapter 是独立的 : binary adapter 也使用同样的代码处理 .
提示 : 唯一不同的地方就是当你直接使用 XML adapter 的特有属性如 Write/ReadXSLT.
如果你希望保持代码的兼容性 , 可以按下面的方式写代码 :
if (MyAdapter is TDAXMLAdapter)
 then TDAXMLAdapter(MyAdapter).WriteXSLT.LoadFromFile := 'c:/test.xsl' ;
XML 格式和 XSLT 转化
XML Data Adapter 的格式非常简单 , 其结构如下 :
< XMLData >
 < Schema >
    < Datasets >
      (this section contains the fields definitions of each dataset
       contained in the document)
    </ Datasets >
    < Deltas >
      (this section contains the definitions of each delta contained
       in the document: the list of the logged fields, their types
       and the key fields)
    </ Deltas >
 </ Schema >
 < Datasets >
    (this section contains the actual data of the datasets)
  </ Datasets >
 < Deltas >
    (this section contains the actual data of the deltas which
     includes information such as change status, message, type, etc.)
  </ Deltas >
</ XMLData >
依赖于我们写入数据流 ( 通过 WriteDataset WriteDelta 方法 ) 的不同内容上面所示的部分可能不包含在最终文档中 . 例如 , 如果我们不写入 Delta, 将不会显示 XMLData/Schema/Deltas XMLData/Deltas. 应该去查看显示的元素而不是假设如何如何 .
这种格式很清晰 , 可用于与已经使用其它格式的系统交换数据 . 例如 , 可能会要求返回 RosettaNet 标准的 XML 格式的数据 (http://www.rosettanet.org/).
XML Adapter 允许你使用 XSLT 脚本与其它格式相互转化 .
如果你对 XSLT 标准不熟悉 , 请看 :
http://www.codeguru.com/Csharp/Csharp/cs_data/xml/article.php/c7801/ (XSLT 指南 , Geoffrey Slinker)
http://maple.cc.kcl.ac.uk/XSLT/ (XSLT 指南 , John Bradley)
XSLT 范例带了两个 XSTL 例子将 Customers 数据转换为不同格式的 XML
DA20 - Data Abstract Adapters_第1张图片
上面的数据包含在 CustomersToSimpleXML.xsl ( 见本文上面的代码连接 ).
Customer 数据转换为 HTML 页面 :
DA20 - Data Abstract Adapters_第2张图片
也在代码连接中查看 CustomersToHTML.xsl XSLT 文件 .
 

你可能感兴趣的:(DA20 - Data Abstract Adapters)