桌面数据库开发.docx
- 文档编号:27436177
- 上传时间:2023-06-30
- 格式:DOCX
- 页数:23
- 大小:32.71KB
桌面数据库开发.docx
《桌面数据库开发.docx》由会员分享,可在线阅读,更多相关《桌面数据库开发.docx(23页珍藏版)》请在冰豆网上搜索。
桌面数据库开发
1.编写桌面数据库应用
1.1.使用数据集
数据集是以行和列的形式组织起来的数据的集合。
其中,每一列具有相同的数据类型,而每行是由各列指定类型的数据组成的。
数据集的每一列被称为一个字段,每一行被称为一个记录。
VCL把数据集封装在一个称为TDataSet的抽象组件中。
在TataSet中引入了许多用于操作和浏览数据集的属性和方法。
1.1.1VCL的数据库体系结构
在开发Delphi3期间,VCL的数据库体系结构已经有了令人注目的修改,为了在Delphi程序中能方便地访问一些非BDE的数据集,它开放了数据集体系结构。
TDataSet类位于整个体系结构的顶层。
TDataSet是一个用来抽象地表示数据集的记录和字段的组件。
为了实现对一些特殊的物理数据格式的访问,你可以在程序中覆盖TDdataSet类的方法。
1.1.2BDE数据访问组件
在组件面板的DataAccess页上可以找到用于访问和管理BDE数据集的VCL组件,如图28-1所示。
VCL用三种组件来表达数据集:
TTable、TQuery和TStoredProc。
TTable是表达数据库表中的数据和结构的组件;TQuery是利用SQL对数据进行查询并返回数据集的组件。
TStoreProc是封装了SQL服务器上的一个存储过程的组件。
本章中,我们将使用TTable组件讨论数据集。
稍后再介绍TQuery组件。
1.1.3打开一个数据集
如果是访问SQL服务器,那么在打开数据库中的一个数据集之前,一定要先建立数据库连接。
当你关闭掉数据库中最后一个数据集时,连接就会终止。
建立和断开数据库的连接都会有一些开销。
如果你经常执行开关数据库的操作,那么应该利用TDatabase组件来管理对SQL服务器的连接。
在对数据集进行操作之前,必须先将它打开。
我们用Open()方法来实现。
请看示例:
Table1.Open();
你也可以通过将数据集的Active属性设为True来打开它:
Table1.Active:
=True;
使用第二种方法的开销更小一些,因为利用Open()方法来实现最终还是要将数据集的Active属性设为True。
不过,这点小开销可以忽略。
当数据集被打开后,我们就可以自由地操作和使用它了。
在一系列的操作完成后,不要忘记要调用Close()方法将它关闭。
如下:
Table1.Close();
当然,你也可以通过把Active属性设为False来关闭数据集。
例如:
Table1.Active:
=False;
1.1.4浏览数据集
TDataSet提供了简单的方法来浏览数据集中的记录。
First()将当前的记录指针定位在数据集中的第一个记录;Last()把当前的记录指针定位在数据集中的最后一个记录;Next()和Prior()分别使当前记录指针向前或向后移动一个记录。
另外,MoveBy()方法用于向前或向后移动一定数量的记录。
1.1.4.1.BOF、EOF和循环
BOF和EOF都是TDataSet中布尔类型的属性,分别表示当前记录是否是第一个记录和最后一个记录。
例如,如果需要遍历数据集中的每一条记录,最容易实现的方法就是利用一个while循环来使指针从第一个记录不断地向后移动直到EOF为真
Table1.First;
WhilenotTable1.Eofdobegin
Dosomething;
Table1.Next;
End;
1.1.4.2.书签
书签能在数据集中保存当前的位置,以便以后可以回到那个位置。
在Delphi中书签的使用非常简单,你只需要使用一个属性。
Delphi用TBookmarkStr类型来表示书签,TTable的Bookmark属性便是此种类型。
当从Bookmark中读值时,你就获取了一个书签;当你写到它时,就可以定位在书签所指示的记录位置。
当你对数据集的某个地方感兴趣并且想能标记以便日后访问时,
Var
BM:
TBookMarkStr;//声明
Begin
BM:
=Table1.BookMark;//定义
………………
Table1.BookMark:
=BM;//回到这个书签标记的位置
BM:
=’’;
End
1.1.4.3.TDataSource
我们在前面的程序中用到了TDataSource组件,所以我们将在这里详细讨论这个组件。
TDataSource是一个数据库连接中介,它使数据访问组件(如TTable)能向数据感知组件提供数据。
它不但在数据访问和数据感知两方面起到了接口的作用,而且,它还包含了一些使数据操作变得更简单的属性和事件。
●TDataSource的State属性表示当前连接的底层数据集的状态。
它可以表明数据集是处于未活动的状态还是插入、编辑、设置键值或是计算字段状态。
●State属性的值的变化会导致发出OnStateChange事件。
TDataSet的OnDataChange事件是在数据集变成活动状态或数据感知组件通知数据集数据发生改变时被触发。
●OnUpdateData事件在记录被提交或更新时被触发,在处理此事件时,一般会改变数据感知组件显示的数据,这种改变依赖于数据库表的内容。
响应此事件你可以使跟踪程序中类似的改变。
1.1.5对字段操作
1.1.5.1.字段值
访问字段的值需要用到TDataset的数组属性Fields[]或FieldsByName()函数。
●Fields[0]将返回一个TField对象,它表示数据集的第一个逻辑字段。
S:
=Table1.Fields[0].AsString
●FieldsByName()函数需要输入字段名作为参数,并返回一个字段对象。
S:
=Table1.FieldsByName(‘Name’).AsString;
1.1.5.2.字段数据类型
TField的DataType属性可以告诉你字段的类型,所返回的字段类型只与数据库类型有关,与ObjectPascal的数据类型无关。
1.1.5.3字段名和编号
●利用TField的FieldName属性能得到某个字段的字段名。
S:
=Table1.Fields[0].FieldName;
●利用FieldNo属性可以获取某个字段对应的编号。
S:
=Table1.FieldsByName(‘Name’).FieldNo;
1.1.5.4.操作字段数据
●编辑
Table1.Edit;
Table1.FieldByName(‘Name’).AsString:
=’LTMa’;
Table1.Post;
Table1.Cancle;//也可以用Cancle来取消操作
●插入
Table1.Insert;//或者Table1.Append
Table1.FieldByName(‘Name’).AsString:
=’LTMa’;
Table1.Post;
Table1.Cancle;//也可以用Cancle来取消操作
●删除
Table1.Last;
Table1.Delete;
数据集在插入、添加或编辑状态时,记住,只要离开当前记录,对数据的改变就会被提交给数据库。
因此,在编辑数据时要小心使用Next()、Prior()、First()、Last()或MoveBy()等方法。
我们可以利用Cancel()方法来取消当前对数据集的修改。
Cancel()方法不但取消了对数据的修改,也同时取消了当前数据集的模式状态,回到了浏览模式
1.1.6刷新数据集
编写数据库程序时,一定要清楚地认识到,数据集中的数据是一直在变化的。
这就是说,数据集中的数据将会不断地被添加、删除或修改,尤其是对于网络环境。
因此,你必须不停地从磁盘或内存中重新读取数据集中的信息来更新当前所使用的数据集。
更新数据集,可以使用TDataset的Refresh()方法。
对Refresh()的调用相当于先调用Close()方法,再调用Open()方法,但是调用Refresh()方法要快一些。
Refresh()方法适用于所有的本地表;而对于来自SQL数据库服务器的数据库,Refresh()方法使用起来有些限制。
在BDE试图进行Refresh()操作之前,必须对SQL数据库表和查询定义一个唯一的索引。
其原因是,Refresh()的调用总是尽可能保持记录当前的状态。
所以,BDE必须使用Seek()来定位到当前的位置,而Seek()操作只对SQL数据集适用,而且要求有一个唯一的索引。
Refresh()并不工作于连接到SQL数据库的TQuery组件。
1.1.7变化的状态
有时候,需要知道一个数据库表当前为编辑模式还是添加模式,或是否处于活动状态,这些信息都可以通过查看TDataset的State属性来获取。
State属性的类型为TDataSetState,
1.1.8过滤器
如果利用过滤器,只要使用ObjectPascal代码就能实现一些简单的数据搜索或过滤。
使用过滤器
最主要的好处是不需要索引,也不需要对数据集做任何其他的准备工作。
当然,过滤器和基于索引的查找比起来,速度还是稍微慢一些(本章后面将会讨论),但另一方面,它们对于任何类型的应用程序都非常有用。
1.1.8.1.过滤一个数据集
Delphi过滤机制的一个比较普遍的作用是只显示数据集中的一些特定记录。
这是一个简单的两步
操作:
1)创建一个处理数据集的OnFilterRecord事件的过程。
在这个过程中,根据一个或多个字段的值来决定是否要包含某个记录。
2)将数据集的Filterd属性设为True。
1.1.8.2.FindFirst/FindNext
TDataSet还提供FindFirst()、FindNext()、FindPrior()和FindLast()等方法。
利用这些方法可以找出那些符合筛选条件的数据记录。
这些方法被OnFilterRecord事件处理过程调用,来对未经过滤的数据集进行操作。
根据OnFilterRecord事件处理过程中给出的过滤条件,可以找出第一个、下一个、前一个或最后一个匹配的记录。
每一个方法都不用输入参数,其返回值是一个表明是否找到匹配记录的布尔值。
1.1.8.3.定位一个记录
TDataSet提供了一个名为Locate()的方法。
由于Locate()使用过滤器进行查找,所以与数据集中的任何索引都没有关系
1.2使用TTable组件
1.2.1查找记录
当需要查找数据库表中的某些记录时,可以使用VCL提供的若干方法。
当使用dBASE和Paradox数据库表时,Delphi会假定被查找的字段都已经被定义了索引。
对SQL数据库表,如果所查找的字段没有定义索引,那么查询的效率将会很低以致于无法忍受。
例如,如果为一个数据库表建立了两个索引,第一个索引基于字段1,它是数值类型的,第二个索引基于字段2,它是字母数字类型的。
这样就可以通过这两个索引查找特定的记录:
即调用FindKey()或者先调用SetKey()再调用GotoKey()。
1.2.1.1.FindKey()
TTable组件的FindKey()方法可用来查找一个与关键字段匹配的记录。
FindKey()需要传递一个arrayofconst类型的参数。
如果调用成功,则返回True。
例如,在下面的代码中,记录指针被定位在这样的记录,其第一个字段取值为123、第二个字段中包含hello字符串。
IfNotTable1.FindKey([123,’Hello’])thenMessageBeep(0);
如果没有找到匹配的记录,FindKey()将返回False,并且计算机发出嘀的一声。
1.2.1.2.SetKey()和GotoKey()
TTable的SetKey()方法能够使数据库表进入设置键值的模式。
在指定了查找条件后就可以调用GotoKey()来从头到尾地搜索一个记录。
前面的例子如果改用SetKey()..GotoKey()来写,则为:
1.2.1.3.最接近的匹配FindNearest()
与前面类似,你也可以调用FindNearest()来查找数据库表中与条件最接近匹配的记录。
例如要查找第一个字段与123最接近的记录,并返回第一个匹配的记录,可以使用下面的代码:
Table1.FindNearest([123]);
同样,FindNearest()也需要传递一组常量作为输入参数,这些常量参数包含的是被查找的记录的字段值。
当查找成功时,如果KeyExclusive属性被设为False,则记录指针将指在第一个匹配的记录上;如果KeyExclusive属性被设为True,则记录指针指在匹配的后一个记录。
1.2.1.4.使用哪个索引
以上的方法都假设你想基于数据库表的主索引来进行查找。
如果使用副索引进行查找,需要设置表对象的IndexName属性来指定一个索引。
例如,如果数据库表有一个基于Company字段的副索引,名为ByCompany,下面的代码查找Unisco公司:
WithTable1dobegin
IndexName:
=’ByCompany’;
FindKey([‘Unisco’]);
End
注意在表打开的情况下,切换索引会有一些额外的开销。
如果在这时设置IndexName属性,可能会有一秒或更多的延迟。
对于dBASE表和Paradox表来说,只能基于定义了索引的字段进行查找。
对SQL数据库来说,如果不是针对定义了索引的字段来设置范围的话,性能将受到损害。
1.2.1.5.SetRange()和ApplyRange()
与FindKey()和FindNearest()类似,SetRange()可以进行复杂的操作。
SetRange()需要传递两组arrayofconst类型的参数,第一组参数表示字段取值范围的下限,第二组则表示字段取值范围的上限。
下面的代码从数据库中过滤出那些第一个字段取值大于等于10并且小于等于15的记录:
Table1.SetRange([10],[15]);
要使用ApplyRange()来设定取值范围,可以按照下面的操作步骤:
1)调用SetRangeStart()方法,并修改数据库表的Fields[]数组属性来设置关键字段的起始值。
2)调用SetRangeEnd()方法,并再次修改Fields[]数组属性来设置关键字段的截止值。
3)调用ApplyRange()建立新的取值范围过滤器。
对前面的例子,可以这样改写:
提示应该尽可能利用SetRange()来过滤记录,因为这样会使代码更简洁,而且出错的可能性
会更小。
如果想要从一个数据库表中取消一个范围过滤器,并且把数据库恢复到调用ApplyRange()前的状
态,可以调用TTable组件的CancelRange()方法,代码如下:
2.开发C/S应用程序
摘自DElPHI5开发人员指南第29章
2.1为什么要采用客户/服务器结构
2.2客户/服务器体系结构
2.3客户/服务器模型
2.4客户/服务器与桌面数据库开发的比较
2.4.1面向集合与面向记录
客户程序并不是像桌面数据库程序那样直接面对数据库表,而只是面对数据的子集。
客户程序在向服务器请求数据时,得到的数据可能是由一个或多个表中的字段构成的,而请求是通过结构化查询语言(SQL)实现的。
通过SQL,客户端可以限制从服务器返回的记录数。
客户端通过SQL语句从服务器上得到结果是服务器上的数据的一个子集。
这一点很重要,因为对于桌面数据库应用程序来说,它通过网络所得到是整个数据库表。
显然,数据库表越大,网络的流量就越大。
客户/服务器系统则不同,它只通过网络传送客户请求的数据,因而网络流量较小,对网络的要求也较低。
这个区别也影响了对SQL数据集的浏览性。
例如第一条、最后一条、下一条和上一条记录等概念,对基于SQL的数据集来说不是固有的。
尤其是当查询结果是由多个数据库表组成的情况下更是如此。
许多SQL服务器提供了可翻滚的指针,用于浏览SQL结果集。
尽管如此,这与桌面数据库的浏览还是不同的,因为后者直接针对数据库表进行浏览。
2.4.2数据安全
SQL数据库处理数据安全的方式与桌面数据库是不同的。
SQL数据库不仅可以对数据库进行口令验证,而且还能够针对特定的数据库对象进行限制,包括视图、数据库表和存储过程等。
这意味着用户访问能够在服务器端定义,来基于用户的需要显示数据。
通常,SQL数据库允许通过GRANT或REVOKE命令向一个用户或一组用户授予或收回权限。
因此,可以在SQL数据库中定义一组用户。
这些权限可以应用于任何一种已经提到的数据库对象。
2.4.3记录锁定方法
锁定是一种机制,使得多个用户可以对同一个数据库提交并发的SQL事务。
锁定级别有多种,不同的服务器有不同的级别。
表一级的锁定主要用于限制对一个正在处理事务的数据库表的访问。
尽管这种方式允许并行的处理,但这种锁定机制速度很慢,因为多个用户往往要共享同一个表。
页面级锁定是一种改进的锁定技术。
用这种技术,服务器可以把数据的某一块锁定在磁盘上,也就是所谓的页面。
当一个事务正在对某页进行处理时,其他事务就不能更新该页上的数据。
由于数据往往分布在数百个页面上,因此多个事务同时操作同一个页面的可能性很小。
有些服务器还提供了记录级的锁定机制,能够锁定数据库表中的某一行。
不过,这样会大大增加锁定信息的维护工作。
桌面数据库采用所谓的保守或明确的锁定策略。
这意味着,无法改变那些当前正在被其他用户更新的记录。
如果试图访问这样的记录,将会出错,错误信息提示除非先前那个用户释放该记录,否则无法访问。
SQL数据库采用所谓的优化锁定策略。
这种技术并不限制访问当前正在被其他用户访问的记录,可以照常对它进行编辑,并请求服务器保存修改后的数据。
不过,在记录被保存之前,首先会与服务器中的备份进行比较,因为在查看和修改这条记录的同时,它可能已被其他用户更新。
如果该记录已被其他用户修改,则会导致一个错误,提示在取得记录后,它已经被更新。
作为一个开发人员,在设计客户程序时应该考虑到这一点,客户/服务器程序尤其要注意到这种情况,而在桌面数据库中就不会发生。
2.4.4数据完整性
对于SQL数据库,可以对服务器中的数据进行更健壮的完整性约束。
尽管桌面数据库也内建了完整性验证的功能,但需要在应用程序的代码中定义一些业务规则。
相对而言,SQL数据库允许在服务器端定义这些规则。
这一点的好处是,不仅可以强制所有的客户端程序都接受同一套规则的约束,而且可以集中维护这些规则。
完整性约束是在服务器上创建数据库表时定义的,完整性约束包括有效性、唯一性和参照性。
完整性约束也可以在SQL存储过程中定义。
例如,在处理一个订单之前,可以先检查顾客的信用。
2.4.5面向事务
SQL数据库是面向事务的。
这意味着,对数据库的修改不是像桌面数据库那样直接针对数据库表进行的,而是由客户请求服务器进行修改,服务器用一个事务来完成这一批操作。
为了确保对数据库的修改能够有效,必须完整地提交事务。
如果事务中的任何一个操作失败,整个事务就会被回滚,换句话说,就是放弃。
事务能够保证服务器上数据的一致性。
还是以前面提到过的存货系统为例,当顾客提交了一份订单后,ORDERS表必须更新。
另外,PARTS表也必须相应地把零件数减少。
如果因为某种原因,系统在更新ORDERS表和PARTS表之间出错,PARTS表中的零件数就不能反映实际情况。
但是,如果把整个操作放在一个事务中,除非整个事务正确地提交,否则,没有一个表会有任何改变。
在Delphi5中,对于事务既可以在服务器层进行控制,也可以在客户层进行控制。
2.5SQL在客户/服务器开发中的角色
2.6Delphi客户/服务器开发
Delphi5提供了一些数据库对象组件,它们封装了BDE的功能。
这样,开发数据库应用程序就不必知道BDE的功能。
其次,Delphi5提供了数据感知组件可以与数据访问组件彼此通信,这样,建立数据库应用程序的界面就变得简单。
SQLLinks为连接Oracle、Sybase、Informix、MicrosoftSQLServer、DB2和InterBase提供了专门的驱动程序
Delphi5还包含了MIDAS技术,“MIDAS:
MultitierDistributedApplicationServicesSuite”。
最后,Delphi允许使用CORBA(CommanObjectRequestBrokerArchitecture)来开发分布式应用程序。
CORBA规范已经被OMG(ObjectManagementGroup)采用。
通过CORBA技术,可以创建面向对象的分布式应用程序
2.7服务器:
后端设计
2.8客户:
前端开发
2.8.1使用TDatabase组件
TDatabse组件可以更有效地控制数据库的连接,包括:
?
建立
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 桌面 数据库 开发