分享
 
 
 

有关TDataSet的研究

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

有关TDataSet的研究

VCL 的数据库框架中有一个很重要的抽象类叫TDataSet ,它可以处理非BDE 的数据源。

鉴于Delphi的很多数据库感知控件都是以TDataSet作为接口和数据库连接的,为了重复使用Delphi现有的资源,已经使我们的小型数据库能更加健壮,更加可移植,已经提出公共接口,针对接口编程,因此决定将原来的GPF控件改写由TDataSet继承。

TDataSet本身自己已经封装了记录缓冲系统。Buffers就是记录它的记录缓冲区的。BufferCount记录可是用缓冲区的个数。但是Buffers的个数比BufferCount多一个。这多出来的一个是TDataSet用来作为临时缓冲区的,即TempBuffer。虽然TDataSet已经封装了,但是对缓冲区的所有实现还得在派生类里实现。但所有在外面可以实现的都是对单个记录缓冲区的。如:为记录缓冲区申请空间,释放空间,初始化缓冲区,以及一些和缓冲区有关的操作。这些在《Delphi 5 开发人员指南》中30章第四节“扩展TDataSet中已经有了很好的说明。

记录缓冲列表

临时缓冲区

0

1

2

3

.

.

.

最后

临时

图1:记录缓冲列表结构

由于TDataSet是个抽象类,所以必须在派生类中实现所有的抽象方法。实现这些抽象方法也正是实现我们的GPF(现改名为GDB)。因为正是这些抽象方法实现了DataSet和数据库数据的连接。最基本的就是InternalOpen和InternalClose两个方法。另外要实现使用Field,就得实现GetFieldData,SetFieldData。这里有一点要说明的是在Fields中的Field的顺序(即用Fields[I]访问的顺序)和数据库中字段的循序是不一样的。我在这里就曾经犯过错误。我的解决方法是使用Field中的属性FieldNo,这个属性可以记录这个字段的物理位置。然后使用FieldByNumber来访问字段。(是不是有点麻烦?我也是没有办法的办法)。当然了,你也可以用一个列表按原始顺序记录Fields的。

TDataSet里的记录号即RecNo这个属性是用来表示当前可以访问的所以记录中按当前访问顺序的第RecNo个记录。感知控件的显示也依赖于这个属性。它不是用来表示记录的物理顺序的。因此,在实现的时候,内部管理记录时要另外使用一个成员变量来表示,相当于一个内部游标。

另外有几个在《开发指南》中没有提到的方法我想说明一下,这几个都与感知控件的显示有关,因此都在Public下的。

IsSquenced这个在TDataSet中Public下的函数,应该继承一下。该方法是用来表示记录的组织是否是连续紧凑的。这个特性在数据库感知控件中会使用到。比如DBGrid中的垂直滚动条的状态就是根据这个来决定的。如果该函数返回真,就是说记录是紧凑的,则滚动条会根据RecNo来决定具体位置。反之,如果是假,则滚动条只有三个状态,即最上、中间、最下。

CompareBookmark这个函数,使用来判断两个记录的大小的。同样,这个函数也与感知控件有关。在DBGrid选择了MultiSelect后,当选择了一条记录后,Grid会根据该函数的返回值来决定是否选中邻近的记录。其实一句话,就是说Grid在这种状态下,会选择所有的相同记录。

另外有一个函数,GetCanModify是实现特性CanModify的。覆盖一下可以用来控制DataSet的ReadOnly。

对在第三段我说的TempBuffer我想在补充几句。TempBuffer这个缓冲区具有很大的作用的,因为它拥有与其他缓冲区相同的特性与操作,而且它对你来说是“生存期自管理”的。这一点在你实现查询操作时会发现很有用。你应该已经有了比较两条记录的函数,但是在查询时,你只有一条记录以及查询条件可以使用。这是你可以将你的查询条件转换成记录,而这条记录就可以放到TempBuffer中。这样你的实现就会变得很统一,因为你做的只是两条记录的比较。

TDataSet另外封装了一点就是书签功能(Bookmark)。一般情况下,Bookmark只要有两个成员变量就行了。一个是Data(TBookmark类型),一个是Flag(TBookmarkFlag)。

Data使用来记录你可以借此而访问到该记录的值。这是个Pointer类型的变量。因此,你可以把它作为整数使用(如存放记录号,我就是这样用的),也可以指向一个记录的指针,甚至于一个记录。而Flag是用来记录当前标签的位置。在Delphi中TbookmarkFlag是这样定义的:TBookmarkFlag = (bfCurrent, bfBOF, bfEOF, bfInserted);其中bfCurrent是表示当前位置,即有效Data。BfBOF和bfEOF表示首尾位置。BfInserted表示刚刚插入还没有提交(Post)的记录。

理解了Bookmark所需要的成员变量以及其意义。我们看一下在TDataSet中Delphi是如何使用Bookmark的。为了便于说明,我先介绍一下我在实现GDB时使用的Bookmark。

下面是结构:

PGDBBookmarkInfo = ^TGDBBookmarkInfo;

TGDBBookmarkInfo = record

BookmarkData: Integer;

BookmarkFlag: TbookmarkFlag;

End;

首先要解决的是Bookmark放在什么地方。这其实对外也是看不见的。上面讲到记录缓冲区,其实Bookmark就是接在记录缓冲区后的。或者更简单的说,整个缓冲区是由记录和Bookmark(TGDBBookmarkInfo结构)组成的。

记录缓冲

书签(TGDBBookmarkInfo)

图2: 记录缓冲区结构

对缓冲区的操作是在TDataSet的派生类里实现的。有几个抽象方法SetBookmarkFlag,SetBookmarkData,GetBookmarkData,GetBookmarkFlag。这几个方法是直接对缓冲区操作的。

TDataSet就是利用这些方法对Bookmark进行操作的。不过,一般设置Bookmark都是在继承类里实现的。实现的位置其实是可以想象的到的。由于Bookmark和记录缓冲区在一起,那么在对记录缓冲区操作的时候(读记录到缓冲区的时候),也就是GetRecord函数中,你可以将与该记录关联的Bookmark写入。正如上面讨论到的,你必须在BookmarkData中填入相应的值。如我这里,就可以填入记录号。以后可以用记录号来访问该记录。

InternalGotoBookmark就是利用BookmarkData来定位到记录的。InternalSetToRecord也是类似的操作。

另外一个由数据感知控件频繁使用的就是CompareBookmarks。它的两个参数就TBookmark类型的。你就是根据这个指针来访问你存放的数据。象我的实现就可以使用Integer(Bookmark1^)来使用。另外,按照我的实现,GetRecNo也可以通过对ActiveBuffer(记录当前活动的缓冲区)的访问来获得的。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有