-
TClientDataSet
用法与简介
与
TTable
、
TQuery
一样,
TClie
ntDataSet
也是从
TDataSet
< br>继承下来的,它通常用于多层体系结构
的客户端。
TCl
ientDataSet
最大的特点是它不依赖于
BDE(Bo
rland Database Engine)
,但它需要一个动态
< br>链接库的支持,这个动态链接库叫
。在客户端,也不需要
用
TDatabase
构件,因为客户
端并不直接连接数据库。
由于
TClientDataSet
是从
p>
TDataSet
继承下来的,所以,它支持诸如编辑、搜索、浏览
、纠错、
过滤等功能。由于
TClientDataSet
p>
在内存中建立了数据的本地副本,上述操作的执行速度很快。也正是由
于
TClientDataSet
并不直接连接数据库,因此
,客户程序必须提供获取数据的机制。在
Delphi 4
中,
TClientDataSet
有三种途径获取数据:
.
从文件中存取数据。
.
从本地的另一个数据集中获取数据。
.
通过
IProvider
接口从远程数据库服务器获取数据。
在一个客户程序中,可以同时运用上述三种机制获取数据。
11.1
浏览和编辑数据
和其他数据集构件一样,可以用标准的数据控件显示由
TClientDataSet
引入的数据集,当然,
这需要借助于
TDataSource
构件。
由于
TClientDataSet
是从
TDataS
et
继承下来的,所以,凡是其他数据集构件支持的功能,
TC
lientDataSet
构件也大致具备。不同的是,
TCl
ientDataSet
能够在内存中建立数据的副本,因此,
TClientDataSet
比其他数据集构件增加了一些特殊的功能。
11.1.1
浏览数据
可以用标准的数据控件显示由
p>
TClientDataSet
引入的数据集。在运行期,可以调用
诸如
First
、
GotoKey
p>
、
Last
、
Ne
xt
和
Prior
等函数来浏览数据。
TCl
ientDataSet
也支持书签功能,可以用书签来标记某条记录,以后就可以方便
地找到这条记
录。
对于
TTable
< br>、
TQuery
等数据集构件来说,只能读
RecNo
属性来判断当前记录的序号。对于
TCl
ientDataSet
构件来说,还可以写
RecNo
属性,使某一序号的记录成为当前记录。
11.1.2
CanModify
属性
TDataSet
的
CanModify
属性用于判断数据集中的数据是否可以修改
。
CanModify
属性本身是只
< br>读的,也就是说,数据是否能够修改不取决于应用程序。
不过
,<
/p>
TClientDataSet
构件有其特殊性
< br>,
因为
TClientDataSet
< br>已经把数据在内存中建立了副本,
因此
,
应用程序可以决定是否允许修改数据
。
如果不允许用户
修改数据
,
只要把
ReadOnly<
/p>
属性设为
True
,
此时,
CanModify
属性肯定返回
< br>False
。
与其他数据集构件不同,修改
TCl
ientDataSet
构件的
ReadOnly
属性时,不需要事先把
Active
属性设为
True
。
11.1.3
取消修改
TClientDataSet<
/p>
传输数据的基本单位称为数据包
,
当前的
数据包可以由
Data
属性来访问
。<
/p>
不过
,
用户对数据的修改并不直接反映到
Data
属性中,而是临时写到一个日志即
Delta
属性中,这样做的好处是
以后随时可以取消修改
。
不过
,这里要说明一点,尽管用户的修改并没有反映到
Data
,当
用户在数据控件中看到的却是
最新修改的数据。如果一条记录被反复修改了多次,用户看
到的只是最新的数据,但日志中却记载了多次。
要取消上一次的修改,调用
Undo
LastChange
函数。
UndoLastChange<
/p>
需要传递一个布尔类型
的参数叫
Foll
owChange
,如果
FollowChange
参数设为
True
,光标就移到被恢复的记录上,
如果
FollowChange
参数设为
False
,光标仍然在当前记录上。
ChangeCount
属性返回日志中记载的修改次数。如果一条记录被反复修改了多次,每调用一次
< br>UndoLastChange
能够逐级取消上一次的修改。
UndoLastChan
ge
只能取消上一次的修改,如果想一下子取消所有的修改,首先要选择一个记
录,然后调用
RevertRecord
。
p>
RevertRecord
将从日志中取消所有对当前记录的修改。
TCl
ientDataSet
还有一个
SavePoint
属性,它能把当前的编辑状态保存起来,以后随时可以返
回当时的状态。
例如,可以这样保存当前的状态:
BeforeChanges := int;
以后,可以这样来恢复当时的状态:
int :=
BeforeChanges;
应用程序可以保存多处状态,可以恢复其中一个状态,不过,一旦某个状态被恢复,在其之后
的状态就无效。
如果要一下子取消日志中记载的所有修改,可以调用
CancelUpda
tes
函数。
CancelUpdates
将
把日志清空,取消所有的修改。
如果
Lo
gChanges
属性设为
False
,用户对数据的修改就会直接反映到
Data
属性中。
11.1.4
合并修改
要把日志中记载的修改合并到
Data
属性中,有两种方式,具体使用哪一种方式,取决于应用程
序获取数据的机制。不过,不
管是哪种机制,合并后,日志自动被清空。
对于一个从文件中获取数据的程序来说,只要调用
MergeChangeLog
函数,就把日志中记载的
< br>修改合并到
Data
属性中。不用担心其他用户同时修改
了数据。
对于一个从应用服务器获取数据的程序来说,就不能调用
MergeChangeLo
g
来合并数据,而要
调用
ApplyU
pdates
函数,
ApplyUpdates
会把日志中记载的修改传递给应用服务器,待应用服务器成功地
把数据更新了数
据库服务器后,才会合并到
Data
属性中。
< br>
11.1.5
纠错
TClientDataSet<
/p>
支持纠错功能。一般情况下,需要自己建立纠错规则,以便对用户输入的数据
进行纠错。
此外,如果获得了
IProvider
接口的话
,还可以从远程服务器引入纠错规则。
有时候,客户端可能需要暂时禁止纠错,因为客户端从应用服
务器检索数据是分阶段进行的,
在所有的数据检索完毕之前,有些纠错规则很可能会报错
。
要暂时禁止纠错,可以调用
p>
DisableConstraints
,要重新允许纠错,可以调
用
EnableConstraints
函
数。
DisableConstraints
和
EnableConstraints
实际上都是作用于一个内部的计数。
11.2
索
引
使用索引有这么几个好处:
.
在数据集中定位记录比较快。
p>
.
能够在两个数据集之间建立
Lookup
或
Master/Detail
关系。
.
可以对记录排序。
在多层体系结构中,当客户程序从
应用服务器检索数据时,它同时获得了默认的索引。默认的
索引叫
DEFAULT_ORDER
,可以使用这个索引排序,但不能修改或删除这个索引。
除了默
认的索引外,
TClientDataSet
还对日志中记载的
记录自动建立了一个副索引叫
CHANGEINDEX
。与
p>
DEFAULT_ORDER
一样,不能修改或删除这个副索引。<
/p>
另外,还
可以使用数据集中已建立的其他索引,或者自己建立索引。
11.2.1
创建一个新的索引
要创建一个新的索引,可以调用<
/p>
AddIndex
。
AddIndex<
/p>
需要传递若干个参数:
一是
Name
参数,用于指定索引名。在运行期切换索引时需要用到索引的名称。
二是
Fi
elds
参数,它是一个字符串,用于指定索引中的字段名,彼此之间用分号隔开。
p>
三是
Options
参数,用于设置索引的选项,包含
ixDescending
元素表示按降序排列,包含
ix
CaseInsensitive
元素表示大小写不敏感。
四是
De
scFields
参数
,
它也是一个字
符串,
用于指定若干个字段名
,这些字段将按照降序排列。
p>
五是
CaseInsFields
参数,它的作用与
DescFields
参数类似,包含在
CaseInsFi
elds
参数中的
字段将对大小写不敏感。
六是
GroupingLevel
参数,用于指定分组级别,其值不能超过索引中的字段数
。
下面的代码创建了一个索引:
If
<> '' and eld() then
Begin
ex(+'Index',,
[ixCaseInsensitive],'','',0);
ame := + 'Index';
End;
为了避免创建一个索引,可以临时用
IndexFieldNames<
/p>
属性来指定若干个字段,让数据集按这些字
段排序。
11.2.2
删除和切换索引
要删除一个先前创建的索引,可以调用
DeleteIndex
并指定要删除的索引名称。注意:
D
EFAULT_ORDER
和
CHANGEINDEX
不能删除。
p>
如果建立了多个索引,可以任意选择其中的一个索引,这就要用到
I
ndexName
属性。
11.2.3
用索引把数据分组
选择了一个索引后,数据集将自动
按其中的字段进行排序。这样,临近的记录往往在关键字段
上含有相同的值。例如,假设
有一个表是这样的:
SalesRep
Customer
OrderNo
Amount
1
1
5
100
1
1
2
50
1
2
3
200
1
2
6
75
2
1
1
10
2
3
4
200
可以看出,
SalesRep
字段的值有重复的。对于
SalesRep
字段的值为
1
的来说,
Customer
字
段的值也有重复的。这就是说,可
以按
SalesRep
字段分组,进而再按
Customer
字段分组。显然,这里
的分组级别是不同
的,按
SalesRep
字段建立的分组属于第一级,按
Customer
字段建立的分组属于第二
级
。实际上,分组级别取决于字段在索引中的顺序。
TClientDataSet
可以
决定是否按照分组级别来显示记录的值。例如,也许想以下面这种形式显
示数据:
SalesRep
Customer
OrderNo
Amount
1
1
5
100
2
50
2
3
200
6
75
2
1
1
10
2
3
4
200
要判断当前记录某一级的什么位置,可以调用
GetGroupState
函数。
GetGroup
State
函数需要
传递一个参数,用于指定分组级别。
11.3
计
算
字
段
p>
与其他数据集一样,也可以在
TClientDataSet
建立的数据集中增加计算字段。计算字段的值是
基于同一个记录中的其
他字段计算出来的。
在其他数据集中,只要用户修改了数据或当前记录发生改变,就会触发
On
CalcFields
事件,换
句话说,计算字段的值就被计算
一次。
TClientDataSet
引入了
“
内部计算字段
”
的概念。与一般的计算字段不同的是,内部计
算字段的值
将随其他字段的值一起存取,这样,只有当用户修改了数据才会触发
OnCalcFields
事件,如果仅仅改变了
当前记录,不会触发
OnCalcFields
事件。也就是
说,内部计算字段的值需要重新计算的机会大大减少。
在处理
OnCalcFields<
/p>
事件的句柄中,首先要判断
State
属
性。如果
State
属性返回
dsIn
ternalCalc
,此时需要计算内部计算字段的值。如果
State
属性返回
dsCalcFields
,此时需要计算一般
的计算字段的值。
11.4
统
计
值
TClientDataSet<
/p>
增加了统计的功能,它可以基于分组自动计算总和、平均、计数、最大、最小
值。当用户编辑数据时,这些统计值会自动跟着变化。
11.4.1
指定统计方式
要指定怎样进行统计,就要用到<
/p>
Aggregates
属性。这个属性是一个
TAggregates
对象,它用于
管理一组
TAggregate
对象。
在设计期,可以单击
Aggregates
属性边上的省略号按钮打开如图
11.1
所示
的编辑器。
图
11.1
管理一组
TAggregate
对象
单击按钮可以增加一个
TAggregate
对象,单击按钮可以删减一个
TAggregate
对象,单击按钮
可以把
TAggregate
对象前移,单击按钮可以把
TA
ggregate
对象后移。
可以用字段编辑器专门创建一个用于表达统计值的字段,该字
段的类型必须是
“Aggregate”
。
Delphi 4
会自动创建一个
TAggregate<
/p>
对象
,
并加到
A
ggregates
属性中
。
选择一个
TAggregate
对象
,
Object
Inpector
将显示该对象
的属性。
其中,
Expression
属性用于指定统计表达式,例如
:
Sum(Field1)
也可以是比较复杂的表达式:
Sum(Qty * Price) - Sum(AmountPaid)
在表达式中,可以使用下列统计运算符:
.Sum
计算一组数据的总和。
.Avg
计算一组数据的平均值。
<
/p>
.Count
计算一组数据中的非空值的个数。
< br>
.Min
计算一组数据的最小值。
-
-
-
-
-
-
-
-
-
上一篇:同事搬新家祝福语50句
下一篇:SAP系统术语