DA17 - Data Abstract 3.0新特性

 
DA17 - Data Abstract 3.0 新特性
导论
Data Abstract 3.0 引入了一系列新特性将改善数据接口以及创建数据驱动中间层的方式 . 本文提供产品的综述和并认识其新特性 .
内容
  • 新的DAServer
  • 改进的DARemoteService
  • 增强动态方法绑定
  • 更新规则
  • Schema Modeler图解
  • 关系和改进的Autoinc支持
  • Automatic同步
  • DALoginService
  • 脚本支持
  • XMLDataAdapter
  • 新的查询生成器
  • 增强的连接向导
  • 新的MiniWH 范例
  • 其他
  • 总结
注意 :
一些图被缩小了如果看不清楚可点击放大 .
新的 DAServer
Data Abstract 3 中提供的 DAServer 是一个可执行的 standalone 服务 .
DAServer ( 简称 DAS) 可以 standalone 应用程序或 NT 服务方式运行并基本上提供你需要的完整的 Schema 多层服务 .
如果你只想生成一个多层应用查询数据, DAServer 将为你提供一个清晰完整的夸数据库风格的解决方案 . DAServer, 结合新的脚本功能允许你不用写中间层代码创建一个及其动态的系统,除非你要那样做 .
当你以 standalone 方式启动 DAS 应用程序 (DAServer.exe), 如下图 :
DA17 - Data Abstract 3.0新特性_第1张图片
在上面的截图 , 已经注册了一个基于 MSSQL Northwind 数据库的 Schema. 关于更多 DAServer 的信息点击 DA15.
改进的 DARemoteService
Data Abstract DARemoteService 为开发者提供很多开发数据驱动服务的基础功能 . 为你实现了诸如 GetSchema, GetDatasetData, UpdateData 等方法使你可直接使用查询服务端的数据集定义 , 实际数据和更新等操作 .
Data Abstract 3, 极大的增强了 IDARemoteService 接口 并提供了一些附加方式使其更简单 , 同时保留 100% 的向后兼容性 .
新方法如下 :
  • GetDatasetDataEx
  • ExecuteSQLCommandEx
  • GetMultipleDatasets
  • GetDatasetScripts
GetDatasetDataEx
function TDARemoteService.GetDatasetDataEx(const DatasetName: String;
                              const Params: TDADatasetParamArray;
                              const UserFilter: String;
                              const IncludeSchema: Boolean;
                              const MaxRecords: Integer): Binary;
var parnames : array of string;
    parvalues : array of variant;
    i : integer;
    options : TDAWriteOptions;
begin
  result := Binary.Create;
 try
    { Prepares the parameter arrays}
    SetLength(parnames, Params.Count);
    SetLength(parvalues, Params.Count);
    for i := 0 to (Params.Count- 1 ) do begin
      parnames[i] := Params[i].Name;
      parvalues[i] := Params[i].Value;
    end;
 
    { Other options }
    if IncludeSchema
      then options := [woSchema, woRows]
      else options := [woRows];
 
    { Reads the data }
    DoGetDatasetData(
       result, Connection, DatasetName, parnames,
       parvalues, UserFilter, ServiceSchema, ServiceAdapter,
       options, MaxRecords);
 except
    FreeAndNIL(result);
    raise;
 end;
end ;
像原来的 GetDatasetData 方法 , 这个方法仍然允许你打开远程数据集的定义信息 , 但是替换掉必须强制提供固定参数名称和参数值的方式 , 改为 TDADatasetParam 数组 .
TDADatasetParam 声明如下 :
{ TDADatasetParam }
TDADatasetParam = class(TROComplexType)
 [..]
published
 property Name:String read fName write fName;
 property Value:Variant read fValue write fValue;
end
值得注意的是 , 如果现在你设置 DataTable Params 值将自动映射到 GetDatasetDataEx 方法 Params 参数 , 除非你明确的设置了他们 .DataTable 引入了一个新的属性 : MaxRecords. 如果你对这个属性设置了一个值 , 讲自动映射到 GetDatasetDataEx 方法的 MaxRecords 参数 .
最后 ,DataTable Where 属性将映射到 UserFilter 参数 .
看如下代码 :
procedure TClientForm.bbManualParametersAssignmentSearchClick(
 Sender: TObject);
var myparams : TDADatasetParamArray;
begin
  myparams := TDADatasetParamArray.Create;
 with ClientDataModule.dtProducts do try
    Close;
 
    with myparams.Add do begin
      Name := 'Name' ;
      Value := eProductName.Text;
    end;
 
    with myparams.Add do begin
      Name := 'BuyPrice' ;
      Value := StrToFloat(eMaxPrice.Text);
    end;
 
    DataRequestCall.ParamByName(par_DatasetName).AsString :=
                                                  LogicalName;
    DataRequestCall.ParamByName(par_Params).AsComplexType := myparams;
    DataRequestCall.ParamByName(par_UserFilter).AsString := '' ;
    DataRequestCall.ParamByName(par_MaxRecords).AsInteger :=
                                                  seMaxProducs.Value;
    DataRequestCall.ParamByName(par_IncludeSchema).AsBoolean := FALSE;
    DataRequestCall.ParamByName(par_MaxRecords).AsInteger :=
                                                  seMaxProducs.Value;
 
    Open;
 finally
    myparams.Free;
 
    // Clears the reference to the garbage pointer
    DataRequestCall.ParamByName(par_Params).Clear;
 end;
end ;
bbManualParametersAssignmentSearchClick Manual Parameters Assignment 按钮的事件处理函数 , 如下图 :
DA17 - Data Abstract 3.0新特性_第2张图片
附加的 UserFilter 参数允许你传递一个 Where 条件选项 , 在客户端生成复杂的数据集筛选条件用于数据集表达式 . UserFilter 属性支持特殊的字段名前缀 ("##") 指明这个客户端使用的字段名已经通过的服务端数据集表达式的 ColumnMapping 提换过 .
看如下代码 :
procedure TClientForm.bbSearchUsingUserFilterClick(Sender: TObject);
begin
 with ClientDataModule.dtCustomers do begin
    Close;
 
    // Prepares the custom WHERE clause
    Where.Clear;
    Where.AddConditions([ 'CustomerIdx' , 'FirstName' , 'LastName' , 'City' ],
                        [cEqual,cLike,cLike,cLike],
                        [eCode.Text,eFirstName.Text,eLastName.Text,
                         eCity.Text], opAnd);
 
    if Where.Empty
      then stWhereClause.Caption := msg_NoCondition
      else stWhereClause.Caption := Where.Clause;
 
    MaxRecords := seMaxCustomers.Value;
 
   { The above is equivalent to:
 
    DataRequestCall.ParamByName(par_UserFilter).AsString:=Where.Clause;
    DataRequestCall.ParamByName(par_MaxRecords).AsInteger :=
                                                   seMaxRecords.Value;
 
    Note: par_UserFilter and par_MaxRecords are constants defined
          in uDADataTable.pas
    }
 
    Open;
 end;
end ;
bbSearchUsingUserFilterClick Search 按钮的事件处理函数 , 如下图 :
DA17 - Data Abstract 3.0新特性_第3张图片
注意 : 上图中间部分的状态行 (grid 上方 ) 显示了当前筛选字符串 (stWhereClause.Caption) , 其中显示了前面讨论的 ’##’ 前缀 . 考虑一下需要的代码 - 虽然我们没有使用所有的筛选条件 , 这里没有出现乏味的 SQL 命令代码 .
ExecuteSQLCommandEx
function ExecuteSQLCommandEx(const CommandName: String;
                          const Params: TDADatasetParamArray): Integer;
var cmd : IDASQLCommand;
    i : integer;
begin
 if not AllowExecuteSQLCommand then
    RaiseError(err_ExecuteSQLCommandNotAllowed);
 
 CheckObjects(Connection, ServiceSchema, NIL, TRUE, TRUE, FALSE);
 
 cmd := ServiceSchema.NewCommand(Connection, CommandName);
 for i := 0 to (Params.Count- 1 ) do
    cmd.ParamByName(Params[i].Name).Value := Params[i].Value;
 
 if Assigned(fOnBeforeExecuteCommand)
    then fOnBeforeExecuteCommand(Self, cmd);
 
 result := cmd.Execute;
 
 if Assigned(fOnAfterExecuteCommand)
    then fOnAfterExecuteCommand(Self, cmd, result);
end ;
ExecuteSQLCommandEx 扩展了原来的 ExecuteCommand 方法 , 允许你通过 Params 参数传递执行存储在服务端的 Schema 中的命令 .
ExecuteSQLCommandEx 通过引用命令名称运行 , 这些命令在不同的数据库有不同的表达式 , 你应确信命令将透明的在不同的数据库上执行 , 而客户端并不知道 .
GetMultipleDatasets
function TDARemoteService.GetMultipleDatasets(
 const DatasetRequestInfoArray: TDADatasetRequestInfoArray)
 : TROBinaryMemoryStream;
var i : integer;
    ds : IDADataset;
    parnames : array of string;
    parvalues : array of variant;
    x : integer;
    opt : TDAWriteOptionS;
begin
  result := NIL;
 if (DatasetRequestInfoArray=NIL) or (DatasetRequestInfoArray.Count= 0 )
    then Exit
    else result := Binary.Create;
 
 ServiceAdapter.Initialize(result, aiWrite);
 try
    for i := 0 to (DatasetRequestInfoArray.Count- 1 ) do
      with DatasetRequestInfoArray[i] do begin
        SetLength(parnames, Params.Count);
        SetLength(parvalues, Params.Count);
        for x := 0 to (Params.Count- 1 ) do begin
          parnames[x] := Params[x].Name;
          parvalues[x] := Params[x].Value;
        end;
 
        opt := [woRows];
        if DatasetRequestInfoArray[i].IncludeSchema then
          opt := opt+[woSchema];
        ds := ServiceSchema.NewDataset(
           Connection, DatasetName, parnames, parvalues, TRUE);
 
        ServiceAdapter.WriteDataset(ds, opt, MaxRecords);
      end;
 
    ServiceAdapter.Finalize;
 except
    FreeAndNIL(result);
    raise
 end ;
end ;
这个函数在单个网络通讯中返回多个数据集从而优化响应时间 . DatasetRequestInfoArray 参数 运行你指定你要传递数据的数据集及其参数 ( 如果确实需要 ). TDADatasetRequestInfo 声明如下 :
{ TDADatasetRequestInfo }
TDADatasetRequestInfo = class(TROComplexType)
 [..]
published
 property DatasetName:String read fDatasetName write fDatasetName;
 property IncludeSchema:Boolean read fIncludeSchema
                                 write fIncludeSchema;
 property MaxRecords:Integer read fMaxRecords write fMaxRecords;
 property Params:TDADatasetParamArray read GetParams write fParams;
end ;
The following code is taken from the new GetMultipleDatasets sample:
procedure TClientForm.bbGetDatasetsClick(Sender: TObject);
var datasets : TDADatasetRequestInfoArray;
    datasetinfo : TDADatasetRequestInfo;
begin
  {
    The following code shows how to manually create this type of request
    using TDADatasetRequestInfo and TDADatasetRequestInfoArray objects.
    This type of code is useful when you want to control the parameters
    of each TDADatasetRequestInfo element.
 
    Keep in mind that the two datasets can actually be opened at design
    time by using the property values set in this demo.
 }
 
  datasets := TDADatasetRequestInfoArray.Create;
 with ClientDataModule do try
    dtCustomers.Close;
 
    with datasets.Add do begin
      DatasetName := 'Customers' ;
      MaxRecords := - 1 ;
      IncludeSchema := FALSE;
    end;
 
    { NewDatasetRequestInfo is a utility function contained in
      uDAInterfaces.pas }
    NewDatasetRequestInfo(datasets, 'Orders' , [], [], FALSE, - 1 );
 
    dtCustomers.DataRequestCall.ParamByName(
                par_DatasetRequestInfoArray).AsComplexType := datasets;
 
    dtCustomers.Open;
 finally
    datasets.Free;
 
    // Cleans garbage pointers
    dtCustomers.DataRequestCall.ParamByName(
                                 par_DatasetRequestInfoArray).Clear;
 end;
end ;
这里一个重点是数据集传输到客户端发生在运行时 .
GetDatasetScripts
function GetDatasetScripts(const DatasetNames: String): String;
这个函数返回有 DatasetNames 参数指定的用逗号分隔的多个数据集列表的业务脚本 .Data Abstract 业务脚本详细信息及支持请见 DA16.
这个功能提供了简单的方式在运行时下载新的脚本 ( 例如 , 当你应用程序启动并第一次连接到远程服务 ).
procedure TProductSearchForm.bbSearchClick(Sender: TObject);
begin
 with ClientDataModule.dtProductsSearch do begin
    Close;
    // Prepares the custom WHERE clause
    Where.Clear;
    Where.AddConditions(
      [fld_ProductsSearchProductName,fld_ProductsSearchProductGroupName,
      fld_ProductsSearchSellPrice, fld_ProductsSearchAvailQty],
      [cLike, cLike, cLessOrEqual, cMajorOrEqual],
      [eName.Text, cbProductGroups.Text,
      StrToFloatDef(eMaxPrice.Text, MillionBucks),
      StrToIntDef(eQuantity.Text, 0 )],
      opAnd);
   
    if Where.Empty
      then stWhereClause.Caption := msg_NoCondition
      else stWhereClause.Caption := Where.Clause;
 
    // Fetches the records
    MaxRecords := seMaxRecords.Value;
    Open;
    AdjustForm(Self);
 end;
end ;
增强的动态方法绑定
动态方法绑定 (DMB) 可能是 Data Abstract 架构最强大的特性 . 本文假设你已经阅读并理解描述其详细功能的文档 DA04. 这里只说一下 Data Abstract 3 中增强的部分 .
今年我们收到很多请求增强或简化 DMB. 对来自客户端 / 服务器的用户 , 不能自然的分开思考方法参数和查询参数 .
例如 , 你定义了一个查询 :
SELECT * FROM Customers WHERE Name LIKE :Name
很多用户感到很惊讶 , 当调用 Schema 向导加载数据集时没有从 DataRequestCall 结构体中找到 "Name" 参数 . 另外一些人注意到如何将 DataTable Params 属性映射到 "Name", 如果其值在调用 Open 前被赋予 , 将不能向中间层传递 .
相关的其他话题使用有个细表数据集 : 细表数据集的属性 MasterRequestMappings 指定主表字段值作为远程方法的参数用于获取子表数据集 . 例如 , 假设你有一个主表 Customers 数据集以及连接的 Orders 数据集 , 为了在 Customres 数据集滚动时获取 Orders 记录 , 你需要如下方法 :
function GetOrders(CustomerIdx: integer) : Binary
begin
result := GetDatasetData(fConnection, 'Orders' ,
                         [ 'CustomerIdx' ], [CustomerIdx]);
end ;
Data Abstract 3 不再需要你去做这些了 . DataTables 现在提供了两中 master mapping 模式 :
1) mmDataRequest
这是最初的映射方式 , 将主表的字段值关联到一个远程方法的参数 . 当你的主表游标滚动 , 细表数据集将调用如上面的 GetOrders 远程方法 , 并使用主表的字段值填充参数 . 这种映射为远程数据获取提供了最大的控制和灵活性 .
2) mmParams
现在在 Data Abstract 3, 在服务端的 Schema 中定义连接到主表数据集字段值的远程数据集参数 . 简单的使用新的 GetDatasetDataEx 方法作为 DataRequestCall 方法 , 当主表数据集滚动 ,GetDatasetDataEx Params 参数将自动赋值而且远程查询的参数将不需要任何自定义方法而自动设置 . 这种映射取消创建像 GetOrders 这样的客户自定义方法 , 除非你实际应用中确实需要自己控制打开数据集 .
下面截图展示 Orders DataTable 的设置 :
DA17 - Data Abstract 3.0新特性_第4张图片
另外 , 主细表组件编辑器已经改进允许你定义新类型映射 :
DA17 - Data Abstract 3.0新特性_第5张图片
其他对 DMB 的增强是有一个新的 MasterOptions/DetailOptions 属性以及 IncludeInAllInOneFetch. 假设你有一个方法要一次获取 Customers Orders , 但是不需要传递 OrderDetails, 这个新的枚举值将指示服务端的 OrderDetails 数据集不去查询数据并加入到流中 . 所以在假设的情形下 , 你应该将 Customers Orders 一次性获取 , OrderDetails 在要求时获取 ( Orders 滚动 ). 这种组合很多 .
更新规则
Data Abstract 2 包含一个叫做 BasicDADemo 的范例 . 其中展示如何做一些稍微复杂的操作 , 如控制 Delta 更新的顺序 , 使用 DMB 获取数据等 . 这些都相对简单 .
其他文档中已经说明当同时发送 Customers,Orders OrderDetails 时如何控制更新顺序 , 而且完全控制所有事情 . 不幸的是这些都需要写代码 .
接下来我们打算重写 BasicDASample 展示如何在 Data Abstract 3 中不写代码做到这些 !
Data Abstract 3 引入了更新规则的概念 , 允许你指定服务端处理 Delta 更新的属性 .
如果你看 DA10 文档 - 深入业务处理器 , 将看到如何写代码实现 .
如下截图将可视化的向你演示如何使用新的 Schema Modeler Data Abstract 3 实现 :
DA17 - Data Abstract 3.0新特性_第6张图片
如果你在 Schema 中定义了一个更新规则 , DARemoteService.UpdateData 方法将按照特定的顺序处理 Delta( 注意 up/down 按钮 ) 而且在一些特定的步骤中只应用适当的更新类型 . 如果你孤立的看可以发现 Delete 顺序和 Insert 的顺序不同 . 考虑到主细表关系中引用完整性约束 , 主表必须先于细表插入而细表必须先于主表删除 . 通过使用 Data Abstract 3 的这个新特性 , 你可以定义一个非常复杂的更新情形而不用写一行代码 , 同时你在服务端存储这些更新规则信息 . 这很重要 , 可以在服务端修改更新规则而不需要变动客户端 .
Schema Modeler 图表
Data Abstract 3 引入了一个期待很久的特性 : 图表 .
DA17 - Data Abstract 3.0新特性_第7张图片
Data Abstract 3 同时也引入了一个新的 TDADiagrams 组件 , 拖放后与你的 Schema 相连 - 如果你启动 SM 并创建图表 , 图表信息将存储在 TDADiagrams 组件中最终存放在 dfm 文件 .
Schema Modeler 只有在启动或者点击的 TDASchema 已经指定 TDADiagrams 组件时候才能获取图表支持 .
你可以在 DA14 中查看更多图表信息 .
关系和改善的 AutoInc 支持
当你在 Schema 中创建两个表的关系时 , 将在 Schema 中创建相应的关系实体并保存在其中 .
例如 , 假如有如下图表 :
DA17 - Data Abstract 3.0新特性_第8张图片
你有如下关系实体 :
DA17 - Data Abstract 3.0新特性_第9张图片
关系向 DARemoteService 提供帮助解决基于 autoinc 字段更新的信息 , 例如在 MiniWH 范例中的 Customers,Orders,OrderDetails. 这些表的主键值是自动增加的 .
当你在客户端插入一条新的 Customers 信息时 ,CustomerIDx 字段的值默认为一个负数 ( 例如 -1).
每个关联到这个新的 Customers Order CustomerIdx 字段都等于 -1 OrderIdx 将也是一些负数 ( 例如 -1, -2 -3 假设我们增加了 3 个订单 ). OrderDetails 应用同样逻辑 .
为解决这些更新 , Data Abstract 2 中要求在代码中自定义方法如 DA10 中的 UpdateThreeLevels 方法并要实现业务处理器的事件如 OnAfterProcessChange . 理由很简单 : 一旦一个新的 Customers 增加到数据库 ,CustomerIdx 值将从 -1 变为一个新数字 ( 1233) 以及所有与之关联的 Order 记录的 CustomerIdx 字段的值也要从 -1 变为 1233.
由于 Schema 关系 (Relationship), 现在将自动进行而不再需要象以前一样写复杂更新方法的代码了 !
 
Data Abstract 3 也考虑到不同数据库 ( Interbase Microsoft SQL Server) 的差异 . Interbase ( Oracle) 不支持 autoInc 字段而是要使用与 autoInc 字段不同的生成器 (Generator). 当你使用生成器 , 在提交记录前必须告诉数据库下一个值 , 相比较而言 autoInc 字段则是在你提交记录后读取最后生成的值 . Data Abstract 3 自动的处理这种差异 , 使用生成器的 DA 连接已经被更新 . 为了实现这个目标向特定的驱动加入一个新接口 :
{ IDAUseGenerators }
IDAUseGenerators = interface
  [ '{7963D550-361E-486A-AAD6-EFD12896F719}' ]
 function GetNextAutoinc(
     const GeneratorName: string): integer; safecall;
end ;
例如 , Interbase Express, ODAC IBObjects 支持这个新的接口 , 业务处理器在读取 autoInc 值时首先判断连接是否支持这个接口 .
另外 ,DA 字段增加了一个新的属性指明用于获取下一个基于生成器的 autoInc 字段值的生成器 . 下图显示了这个新属性 :
DA17 - Data Abstract 3.0新特性_第10张图片
MSSQL 数据库的 Order 表中不需要使用这个属性 . 而对以 Interbase 数据库 , 使用这个属性在记录提交到 DB 后自动调用 IDAUseGenerators.GetNextAutoinc.
自动生成字段同步
Autoinc 字段 , 数据库触发器或客户定义的服务端方法都可能在 Delta 应用之前或之后修改 Delta. 例如 , 假设 Order 表中的 TotalPrice 字段需要在记录提交到数据库前在服务端计算 . 如果这样 , 客户端或者要重新获取这个数据集实体或者在数据库中读取新值后将之返回到客户端 . 然而在 Data Abstract 2 中必须要写代码实现 ( DA10 中的例子 ), Data Abstract 3 中则不在需要了 .
数据集的字段已经被一个新的 ServerAutoRefresh 属性扩展 , 指示远程服务在记录提交后重新读取行并将新值发送回客户端 . 例如 , 我们设置 Orders.TotalPrice ServerAutoRefresh 属性为 TRUE, 在记录提交以后服务将自动发出一个 SELECT TotalPrice FROM Orders WHERE [..] 查询 . 更新查询中只包含标记为 ServerAutoRefresh 的字段以便于提高执行效率 .
因而如果你的数据集字段被触发器 , 业务代码或其他过程修改 , 只需要设置这个属性为 TRUE, 不需要写代码你的 DataTable 将在单一的网络往返中自动自我更新 !
DALoginService
多数系统都需要一个窗体做用户登陆 . 基于此 Data Abstract 3 引入一个新的同 DARemoteService 的使用方式一样的基础服务 . 这个基础服务叫做 DALoginService 并定义如下 :
{ IDALoginService }
IDALoginService = interface(IDARemoteService)
 [ '{58550AA0-B64F-495A-B2F8-C981D4C39180}' ]
 function Login(const UserID: String;
     const Password: String; out LoginInfo: TDALoginInfo): Boolean;
 procedure Logout;
end ;
Login 获取 UserID Password 参数并使用它们生成一个查询如
SELECT * FROM Users WHERE UserID=:UserID AND UserPassword=:UserPassword
如果查询返回一个单一记录登陆成功 , 返回 TRUE 并生成一个如下声明的 TDALoginInfo 结构 :
{ TDALoginInfo }
TDALoginInfo = class(TROComplexType)
 [..]
published
 property SessionID:String read fSessionID write fSessionID;
 property UserID:String read fUserID write fUserID;
 property Privileges:TDAStringArray read GetPrivileges
                                     write fPrivileges;
 property Attributes:TDAStringArray read GetAttributes
                                     write fAttributes;
 property Data:Binary read GetData write fData;
end ;
 
SessionID UserID 属性将自动填充 , 你可以选择使用这些剩余的参数向客户端返回自定义的值 .
更多关于登陆处理的解释将在说明 MiniWH 的文档中推出 , 但是现在值得看一下 DALoginService 数据模块的一些属性 :
DA17 - Data Abstract 3.0新特性_第11张图片
LoginDataset 属性允许你指定哪个 Schema 的数据集去验证 UserID Password.
ParamNameUserID ParamNamePassword 允许你指定要接收 UserID Password 值得参数名字 .
可选的 LogoutCommand ParamNameSessionID 属性指示当 Logout 执行时 DALoginService 自动执行一个特殊的 SQL 命令 , 这个 SQL 命令期望使用 SessionID( 字符串 ) 参数 .
OnLogin , OnLoginFailure, OnLoginSuccess OnLogout 事件允许你在登陆过程的各个阶段自定义服务行为 . 例如 , 假设你的客户端发送 UserID Password, 但是你在数据库存储的是加密格式 , 这时可以在 OnLogin 事件中作如下处理 :
procedure TLoginService.DALoginServiceLogin(Sender: TDALoginService;
var aUserID, aPassword: String);
begin
  aPassword := EncryptPassword(aPassword);
 aUser := UpperCase(aUser);
end ;
这个事件执行后 , 将为 LoginDataset 属性指定的数据集提供新的 UserID password 参数值然后打开这个登陆数据集作具体验证 .
脚本支持
脚本在 DA16 中详细介绍 .
业务规则脚本提供了一种解决方案 , 可以集中的在 Schema 中同数据一起定义客户端业务规则 . 你可以继续使用熟悉的 Pascal 代码写业务规则而且这些规则将自动传送到客户端并在客户端执行 . 当业务规则需要变化只需在 Schema 中修改 , 客户端使用 DARemoteService.GetScripts 方法获取新的业务规则 .
新的 DAServer 允许你传递脚本而且这两种工具在一起运行良好 .
XMLDataAdapter
Data Abstract 3 引入期望已久的返回平台无关的数据的 XML Adapter.
注意 : 3.01 版本 ,XMLAdapter 还不完整但是计划在后面版本中更新 .
点击 TDAXMLAdapter 控件 , 可以在属性编辑器中看到如下属性 :
DA17 - Data Abstract 3.0新特性_第12张图片
TDAXMLAdapter 输出如下所示的 XML 格式 :
< XMLData >
 < Schema >
    < Datasets >
      < Customers >
          < Fields >
             < Field Alignment =" taLeftJustify " BlobType =" dabtUnknown "
                    BusinessRulesID ="" Calculated =" False "
                    CustomAttributes =" 10772264 " DataType =" datAutoInc "
                    DefaultValue ="" Description ="" DictionaryEntry =""
                    DisplayFormat ="" DisplayLabel =" CustomerIdx "
                   DisplayWidth =" 0 " EditFormat ="" EditMask =""
                    GeneratorName =" CUSTOMERIDXGEN " InPrimaryKey =" True "
                   KeyFields ="" LogChanges =" True " Lookup =" False "
                    LookupCache =" False " LookupKeyFields =""
                   LookupResultField ="" LookupSource =" 0 "
                    Name =" CustomerIdx " ReadOnly =" False " RegExpression =""
                   Required =" True " ServerAutoRefresh =" True "
                    Size =" 0 " SqlOrigin =" CustomerIdx " Visible =" True " />
          Fields >
      Customers >
    Datasets >
  Schema >
 < Data >
    < Customers >
        < Row CustomerIdx =" 50 " FirstName =" Amity " LastName =" Nappier "
             Address1 =" 4754 Dominion Street " City =" Rollinsford "
             State =" PR " Zip =" 35295 " Phone1 =" (247) 891-9858 "
             Email =" [email protected] "
              CreditCard =" 5981417510866867 " />
    Customers >
  Data >
XMLData >
通过 SchemaOptions.soIncludeAllAttributes 属性值可以控制是否包含字段定义 , RowOptions.roCompressBlobs 属性控制是否在编码前压缩 blob 数据 .
IncomingXSLT OutgoingXSLT 属性允许你对各自的 XML 流做应用 XSLT 转换 . 例如 , 如果你从 .NET web service 中接收一个 ADO.Net Dataset, 你应该使用 IncomingXSLT 属性指定 XSLT 文件映射到 Data Abstract 格式 . 当将数据集返回时需要使用 OutgoingXSLT 属性指定相反的转换 .
查看压缩文件 ( 见本文上面的连接 ) 中的 Customers.xml 文件 . 其中包含了从 MiniWH 范例中抽取的 Customers 例子而且还有一个可以将 Customers.XML 转换为 HTML XSLT 文件 .
XML Adapter 通常用于为外部系统提供接口的情况 . ADO.NET 的映射将在下一个版本中提供 , 这样就可以在 Win32 .NET Pocket PC(CF) 之间传递数据了 .
新的查询生成器
Schema Modeler 新的 Build Query 工具栏按钮提供了一个可以轻松实现 JOINs 或复杂 WHERE 子句的查询生成器 :
DA17 - Data Abstract 3.0新特性_第13张图片
通过 Data Abstract 3 提供的增强主外键元数据支持是自动连接查询成为可能 . 更多信息请看 DA14.
增强的连接向导
生成一个初始的连接过程是不同的 , 不幸的是这是第一个要做的工作 . Data Abstract 3 提供了一个动态帮助面板显示特定数据库连接信息 . 注意这两个截图的不同 :
DA17 - Data Abstract 3.0新特性_第14张图片
DA17 - Data Abstract 3.0新特性_第15张图片
帮助面板将在后面的版本中有所变动 , 你可以从 FAQ37 获取最新信息 .
新的 MiniWH 范例
 
MiniWH 范例 (mini warehouse) 需要独立安装 , 其中包含可执行的服务端和客户端执行以及需要的数据库文件 . 提供了如下终端数据库版本支持 :
  • Microsoft SQL Server 2000
  • FireBird 1.5
  • DBISAM 4
  • Oracle
  • Sybase
DA17 - Data Abstract 3.0新特性_第16张图片
范例将使连接到多个数据库终端很简单 , 而且向你展示如果做到很酷的效果 ( 包括很好的 N 层设计模式 ). 计划生成一个文档说明这个范例 . 你可以点击 here 查看 , 但是请记住这是一个循序渐进的工作一些小节将会变动或删除 .
其他
其他增强包括 :
  • DARemoteService.AutoCreateBusinessProcessors 属性:由于这个属性你不比再为每个要更新的数据集拖放一个TDABusinessProcessor. Data Abstract 3中如果你要用代码指定特殊的业务逻辑只需要拖放一个业务处理器组件.其他时候将自动为你处理.
  • DARemoteService.AllowExecuteSQLCommand: 这个属性允许你阻止恶意用户远程调用ExecuteSQLCommand执行SQL命令. 注意:这个特性不是最终版可能在以后版本中扩展改进.
  • DADesignTimeCall 组件: 拖放它到客户端窗体可以帮助测试,设置其RemoteService RemoteRequest.MethodName 属性就可以在设计时执行远程查询.DA15中查看在客户端存取DAServer”的更多信息.
总结
本文对 Data Abstract 3.0 的新特性和增强支持提供了简短的讨论 .
重点包括 :
  • DAServer: 新的standalone可执行服务 (DA15)
  • 改进的 DARemoteService: 附加方法- GetDatasetDataEx, ExecuteSQLCommandEx, GetMultipleDatasets GetDatasetScripts
  • 增强了TDAWhere ColumnMappings: 更有效率的生成夸数据库解决方案
  • 动态方法绑定的增强:使用新的GetDatasetDataEx 调用减少自定义方法
  • 更新规则:不用代码就可以控制主细表更新顺序
  • Schema Modeler 图表:通过拖放生成数据集及其关系(article DA14)
  • Relationships 和改进的Autoinc支持:使用关系提供的支持可以不用写代码处理自动增加字段的autoIncGenerator问题
  • Automatic 字段同步:服务端的值变化可以自动的反映到客户端
  • DALoginService: 不需要代码就可以使用扩展的login/logout
  • 脚本支持:允许客户端执行存放在服务端的业务规则
  • XML Data Adapter: better connectivity with external systems
  • 新的查询生成器
  • 增强的连接向导:新的帮助面板
  • 新的MiniWH 范例:展示如果使用DA的一些特性
 
从上面的列表中可见 , 我们主要的设计目标就是减少处理日常数据关系和多层问题的代码量 .
请关注下一篇文档 " 使用 MiniWH 范例 ". 其中包含了上面提到的所有方面 , 提供了对使用 Data Abstract 有用的概述 .
 
 

你可能感兴趣的:(Data,Abstract文档翻译)