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),
如下图
:
在上面的截图
,
已经注册了一个基于
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
按钮的事件处理函数
,
如下图
:
附加的
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
按钮的事件处理函数
,
如下图
:
注意
:
上图中间部分的状态行
(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
的设置
:
另外
,
主细表组件编辑器已经改进允许你定义新类型映射
:
其他对
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
实现
:
如果你在
Schema
中定义了一个更新规则
, DARemoteService.UpdateData
方法将按照特定的顺序处理
Delta(
注意
up/down
按钮
)
而且在一些特定的步骤中只应用适当的更新类型
.
如果你孤立的看可以发现
Delete
顺序和
Insert
的顺序不同
.
考虑到主细表关系中引用完整性约束
,
主表必须先于细表插入而细表必须先于主表删除
.
通过使用
Data Abstract 3
的这个新特性
,
你可以定义一个非常复杂的更新情形而不用写一行代码
,
同时你在服务端存储这些更新规则信息
.
这很重要
,
可以在服务端修改更新规则而不需要变动客户端
.
Schema Modeler
图表
Data Abstract 3
引入了一个期待很久的特性
:
图表
.
Data Abstract 3
同时也引入了一个新的
TDADiagrams
组件
,
拖放后与你的
Schema
相连
-
如果你启动
SM
并创建图表
,
图表信息将存储在
TDADiagrams
组件中最终存放在
dfm
文件
.
Schema Modeler
只有在启动或者点击的
TDASchema
已经指定
TDADiagrams
组件时候才能获取图表支持
.
你可以在
DA14
中查看更多图表信息
.
关系和改善的
AutoInc
支持
当你在
Schema
中创建两个表的关系时
,
将在
Schema
中创建相应的关系实体并保存在其中
.
例如
,
假如有如下图表
:
你有如下关系实体
:
关系向
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
字段值的生成器
.
下图显示了这个新属性
:
在
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
数据模块的一些属性
:
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
控件
,
可以在属性编辑器中看到如下属性
:
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
"
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
子句的查询生成器
:
通过
Data Abstract 3
提供的增强主外键元数据支持是自动连接查询成为可能
.
更多信息请看
DA14.
增强的连接向导
生成一个初始的连接过程是不同的
,
不幸的是这是第一个要做的工作
. Data Abstract 3
提供了一个动态帮助面板显示特定数据库连接信息
.
注意这两个截图的不同
:
帮助面板将在后面的版本中有所变动
,
你可以从
FAQ37
获取最新信息
.
新的
MiniWH
范例
MiniWH
范例
(mini warehouse)
需要独立安装
,
其中包含可执行的服务端和客户端执行以及需要的数据库文件
.
提供了如下终端数据库版本支持
:
- Microsoft SQL Server 2000
- FireBird 1.5
- DBISAM 4
- Oracle
- Sybase
范例将使连接到多个数据库终端很简单
,
而且向你展示如果做到很酷的效果
(
包括很好的
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支持:使用关系提供的支持可以不用写代码处理自动增加字段的autoInc和Generator问题
- Automatic 字段同步:服务端的值变化可以自动的反映到客户端
- DALoginService: 不需要代码就可以使用扩展的login/logout
- 脚本支持:允许客户端执行存放在服务端的业务规则
- XML Data Adapter: better connectivity with external systems
- 新的查询生成器
- 增强的连接向导:新的帮助面板
- 新的MiniWH 范例:展示如果使用DA的一些特性
从上面的列表中可见
,
我们主要的设计目标就是减少处理日常数据关系和多层问题的代码量
.
请关注下一篇文档
"
使用
MiniWH
范例
".
其中包含了上面提到的所有方面
,
提供了对使用
Data Abstract
有用的概述
.