桌面数据库开发_第1页
桌面数据库开发_第2页
桌面数据库开发_第3页
桌面数据库开发_第4页
桌面数据库开发_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1. 编写桌面数据库应用1.1. 使用数据集数据集是以行和列的形式组织起来的数据的集合。其中,每一列具有相同的数据类型,而每行是由各列指定类型的数据组成的。数据集的每一列被称为一个字段,每一行 被称为一 个记录。 V C L 把数据集封装在一个称为 TDataSet 的抽象组件中。在 TataSet 中 引入了许多 用于操作和浏览数据集的属性和方法。1.1.1 VCL 的数据库体系结构在开发 Delphi 3 期间, V C L 的数据库体系结构已经有了令人注目的修改,为了在D e lp h i 程序中能方便地访问一些非 B D E 的数据集,它开放了数据集体系结构。 TData S e t

2、类位于整个体系结构的顶层。 T D a t a S e t 是一个用来抽象地表示数据集的 记录和字段的组件。为了实现对一些特殊的物理数据格式的访问,你可以在程序中覆盖 T D d a t a S e t类的方法。1.1.2 BDE 数据访问组件在组件面板的 Data Access 页上可以找到用于访问和管理B D E 数据集的 V C L 组件,如图 2 8 - 1 所示。 V C L 用三种组件来表达数据集: T Ta b l e 、 T Q u e r y 和 T S t o r e d P r o c 。 T Ta b l e 是表达数据库表中的数据和结构的组件; T Q u e r y

3、 是 利用 SQ L 对数据 进行查询并返回数据集的组件。 TS t o r e P r o c 是封装了 SQ L 服 务器上的一个存储过程的组件。本章中,我们将使用 T Ta b l e 组件讨论数据集。稍后 再介 绍 T Q u e r y 组件。1.1.3 打开一个数据集如果是访问 S Q L 服务器,那么在打开数据库中的一个数据集之前,一定要先建立数据库连接。当你关闭掉数据库中最后一个数据集时,连接就会终止。 建立和断开数据库 的连接都会有一些开销。如果你经常执行开关数据库的操作,那么应该利用 T D a t a b ase 组件来管 理对 SQL 服务器的连接。在对数据集进行操作之

4、前,必须先将它打开。我们用 O p e n ( ) 方法来实现。请看示例:Table1.Open();你也可以通过将数据集的 A c t i v e 属性设为 Tr u e 来打开它:Table1.Active:=True;使用第二种方法的开销更小一些,因为利用 O p e n ( ) 方法来实现最终还是要将数据集的 A c t i v e 属性设为 Tr u e 。不过,这点小开销可以忽略。当数据集被打开后,我们就可以自由地操作和使用它了。在一系列的操作完成后, 不要忘记要调用 C l o s e ( ) 方法将它关闭。如下:Table1.Close();当然,你也可以通过把A c t i

5、v e 属性设为 F a l s e 来关闭数据集。例如:Table1.Active:=False;1.1.4 浏览数据集T D a t a S e t 提供了简单的方法来浏览数据集中的记录。 First() 将当前的记录 指针定位在数据集中的第一个记录; L a s t ( ) 把当前的记录指针定位在数据集中的最后一个记录; Nex t ()和 P r io r () 分别使当前记录指针向前或向后移动一个记录。另外, M o v e B y ( ) 方法用于向前或向后移动一定数量的记录。. BOF 、 E O F 和循环B O F 和 E O F 都是 TDa t a Set

6、中布尔类型的属性,分别表示当前记录是否是第一个记录和最后一个记录。例如,如果需要遍历数据集中的每一条记录,最容易实现的 方法就是利用一个w h i l e 循环来使指针从第一个记录不断地向后移动直到 E O F 为真Table1.First;While not Table1.Eof do beginDo something;Table1.Next;End;. 书签书签能在数据集中保存当前的位置,以便以后可以回到那个位置。在 D e l p h i 中 书签的使用非常简单,你只需要使用一个属性。 Delphi 用 T B o o k m a r k S t r 类型来表示书签, T

7、 Ta b l e 的 Bookmark 属性便是此种类型。当从B o o k m a r k 中读 值时,你就获取了一个书签;当你写到它时,就可以定位在书签所指示的记录位置。当 你对数据集的某个地方感兴趣并且想能标记以便日后访问时,VarBM:TBookMarkStr;/ 声明BeginBM:=Table1.BookMark;/ 定义Table1.BookMark:=BM;/ 回到这个书签标记的位置BM:= '' ;End. TDataSource我们在前面的程序中用到了 T D a t a S o u r c e 组件,所以我们将在这里详细讨论这个组件。 T

8、D a t a S o u r c e 是一个数据库连接中介,它使数据访问组件 ( 如 T Ta b l e ) 能向数据感知组件提供数据。它不但在数据访问和数据感知两方面起到了接口的 作用,而 且,它还包含了一些使数据操作变得更简单的属性和事件。T D a t a S o u r c e 的 S t a t e 属性表示当前连接的底层数据集的状态。它可以表明数据集是处于未活动的状态还是插入、 编辑、设置键值或是计算字段状 态。S t a t e 属性的值的变化会导致发出 O n S t a t e C h a n g e 事件。 T D a t a S e t 的 O n D a t a C

9、 h a n g e 事件是在数据集变成活动状态或数据感知组件通知数据集数据发生改变时被触发。On U p d a t e D a t a 事件在记录被提交或更新时被触发,在处理此事件时,一般会改变数据感知组件显示的数据, 这种改变依赖于数据库表的内容。 响应此事件你可以使跟踪程序中类似的改变。1.1.5 对字段操作. 字段值访问字段的值需要用到 T D a t a s e t 的数组属性 F i e l d s 或 F i e l d s B y N a m e ( ) 函数。F i e l d s 0 将返回一个T F i e l d 对象,它表示数据集的第一个逻辑字 段。S

10、:=Table1.Fields0.AsStringF i e l d s B y N a m e ( ) 函数需要输入字段名作为参数,并返回一个字段对象。S:= Table1.FieldsByName( Name' ).AsString;. 字段数据类型T F i e l d 的 D a t a Ty p e 属性可以告诉你字段的类型,所返回的字段类型只与 数据库 类型有关,与 O b j e c tP a s c a l 的数据类型无关。. 字段名和编号利用 T F i e l d 的 F i e l d N a m e 属性能得到某个字段的字段名 S:=

11、Table1.Fields0.FieldName;利用 F i e l d N o 属性可以获取某个字段对应的编号。S:= Table1.FieldsByName( Name' ).FieldNo;. 操作字段数据编辑Table1.Edit;Table1.FieldByName( Name ' ).AsString:= ' LTMa ' ;Table1.Post;Table1.Cancle;/ 也可以用 Cancle 来取消操作 插入Table1 Insert;/ 或者 Table1.AppendTable2 FieldByName( Name &

12、#39; ).AsString:= ' LTMa ' ;Table1.Post;Table3 Cancle;/ 也可以用 Cancle 来取消操作 删除Table1.Last;Table4 Delete; 数据集在插入、添加或编辑状态时,记住,只要离开当前记录,对数据的改变就会被提交给数据库。 因此,在编辑数据时要小心使用 N e x t ( ) 、 P r i o r ( ) 、 Fi rs t ( ) 、 L a s t ( ) 或 M o v e B y ( ) 等方法。我们可以利用 C a n c e l ( )方法来取消当前对数据集的修改。 C a n c e l (

13、 ) 方法不但取消了对数据的修改,也同时取消了当前数据集的模式状态,回到了浏览模式1.1.6 刷新数据集编写数据库程序时,一定要清楚地认识到,数据集中的数据是一直在变化的。这就是说,数据集中的数据将会不断地被添加、删除或修改,尤其是对于网络环境。因此, 你必须不停地从磁盘或内存中重新读取数据集中的信息来更新当前所使用的数据集。更 新数据集,可以使用 TDataset 的 R e f re s h () 方法。对 R e f re s h () 的调用相当于先调用 C l o s e ( ) 方法,再调用 O p e n ( ) 方法,但是调用 R e f r e s h ( ) 方法要快一些。

14、 Re f r es h ()方法适用于所有的本地表;而对于来自 S Q L 数据库服务器的数据库, R e f r e s h ( ) 方法使用起来有些限制。在 B D E 试图进行 R e f r e s h () 操作之前,必须对S Q L 数据库表和查询定义一个唯一的索引。其原因是, R e f r e s h ( ) 的调用总是尽可能保持记录当前的状态。所以, B D E 必须使用 S e e k() 来定位到当前的位置,而S e e k () 操作只对 S Q L 数据集适用,而且要求有一个唯一的索引。 R e f r e s h ( ) 并不工作于连接到 S Q L 数据库的 T

15、 Q u e r y 组件。1.1.7 变化的状态有时候,需要知道一个数据库表当前为编辑模式还是添加模式,或是否处于活动状态,这些信息都可以通过查看TDataset 的 S t a t e 属性来获取。 S t a t e 属性的类型为 T Da t a S e t S t a t e1.1.8 过滤器如果利用过滤器,只要使用 Object Pascal 代码就能实现一些简单的数据搜索或过滤。使用过滤器最主要的好处是不需要索引,也不需要对数据集做任何其他的准备工作。当然,过 滤器和基于索引的查找比起来,速度还是稍微慢一些 ( 本章后面将会讨论) ,但另一方面, 它们对于任何类型的应用程序都非常

16、有用。. 过滤一个数据集D e l p h i 过滤机制的一个比较普遍的作用是只显示数据集中的一些特定记录。这是一个简单的两步操作:1) 创建一个处理数据集的 O n F i l t e r R e c o r d事件的过程。在这个过程中,根据一个或多个字段的值来决定是否要包含某个记录。2) 将数据集的 F i l t e r d 属性设为 Tr u e 。. FindFirst/FindNextT D a t a S e t 还提供 F i n d F i r s t ( )、 F i n d N e x t ( )、 F i n d Pr i o r () 和

17、F i n d L a s t () 等方法。利用这些方法可以找出那些符合筛选条件 的数据记录。这些方法被O n F i l t e r R e c o r d事件处理过程调用,来对未经过滤的数据集进行操作。根据O n F i l t e r R e c o r d事件处理过程中给出的过滤条件,可以找出第一个、下一个、前一个或最后一个匹配的记录。每一个方法都不用输入参数,其返回值是一个表明是否找到匹配记录的布尔值。. 定位一个记录T D a t a S e t 提供了一个名为 L o c a t e () 的方法。由于L o c a t e () 使用过滤器进行查找,所以与数据集

18、中的任何索引都没有关系. 使用 TTable 组件1.2.1 查找记录当需要查找数据库表中的某些记录时,可以使用 V C L 提供的若干方法。当使用 d B A SE和P a r a d o x数据库表时,Delphi会假定被查找的字段都已经被定义了索引。对 S Q L数据库表,如果所查找的字段没有定义索引,那么查询的效率将会很低以致于无法 忍受。例如,如果为一个数据库表建立了两个索引,第一个索引基于字段1 ,它是数值类型的,第二个索引基于字段2 ,它是字母数字类型的。这样就可以通过这两个索引查找特定的记录:即调用 F i n d K e y ( ) 或者先调用 S e t K

19、e y ( ) 再调用 G o t o K e y( ) 。. FindKey()T Ta b l e 组件的 F i n d K e y ( ) 方法可用来查找一个与关键字段匹配的记录。F i n d K e y ( ) 需要传递一个a r r a yof const类型的参数。如果调用成功,则返回 Tr u e 。例如,在下面的代码中,记录指针被定位在这样的记录,其第一个字段取值为 1 23 、第二个字段中包含h e l l o 字符串。If Not Table1.FindKey(123, ' Hello ' ) then MessageBeep(0);如果没

20、有找到匹配的记录, F i n d Ke y () 将返回 F a l s e ,并且计算机发出嘀的一声。. SetKey() 和 G o t o K e y ( )T Ta b l e 的 S e t K e y ( ) 方法能够使数据库表进入设置键值的模式。在指定了 查找条件后就可以调用 G o t o K e y ( ) 来从头到尾地搜索一个记录。前面的例子如果 改用 S e t K ey ( ) . . G o to K e y ()来写,则为:. 最接近的匹配F i n d N e a r e s t ( )与前面类似,你也可以调用 F i n d N e

21、 a r e s t ( )来查找数据库表中与条件最接近匹配的记录。例如要查找第一个字段与 1 2 3 最接近的记录,并返回第一个匹配的记录,可以使用下面的代码:Table1.FindNearest(123);同样, F i n d N e a r e s t ( )也需要传递一组常量作为输入参数,这些常量参数包含的是被查找的记录的字段值。当查找成功时,如果 K e y E x c l u s i v e 属性被设为 F a l s e ,则记录指针将指在第一个匹配的记录上;如果K e y E x c l u s i v e 属性被设为 Tr u e ,则记录指针指在匹配的后一个记录。1.2.

22、1.4. 使用哪个索引以上的方法都假设你想基于数据库表的主索引来进行查找。如果使用副索引进行查 找,需要设置表对象的 I n d e x N a m e 属性来指定一个索引。例如,如果数据库表有一个基于 Co m p a n y 字段的副索引,名为 B y C o m p a n y ,下面的代码查找U n i s c o 公司:With Table1 do beginIndexName:= ' ByCompan ' y ;FindKey( Unisco' );End注意在表打开的情况下,切换索引会有一些额外的开销。如果在这时设置 I n d e x N a me 属性

23、,可能会有一秒或更多的延迟。 对于 d B A S E 表和 P a r a d o x 表来说,只能基于定义了索引的字段进行查找。对S Q L 数据库来说,如果不是针对定义了索引的 字段来设置范围的话,性能将受到损害。. SetRange() 和 ApplyRange()与 F i n d K e y () 和 F i n d N e a re s t ()以进行复杂的操作。 S e t R a n g e ( ) 需要传递两组数表示字段取值范围的下限,第二组则表示字段取值范围的上限。下面的代码出那些第一个字段取值大于等于 1 0 并且小于等于类似, S e t R a n g

24、 e () 可 a r r a yof const 类型的参数, 第一组参 从数据库中过滤Table1.SetRange(10,15);要使用 A p p l y R a n g e ( )1) 调用 S e t R a n g e S t a r t ( ) 数组属性来设置关键字段的起始值。2) 调用 S e t R a n g e E n d () 设置关键字段的截止值。3) 调用 A p p l y R a n g e ()对前面的例子,可以这样改写:1 5 的记录:来设定取值范围,可以按照下面的操作步骤:方法,并修改数据库表的 F i e l d s 方法,并再次修改 F i e l

25、d s 数组属性来建立新的取值范围过滤器。提示应该尽可能利用 S e t R a n g e ( ) 来过滤记录,因为这样会使代码更简洁, 而且出 错的可能性会更小。 如果想要从一个数据库表中取消一个范围过滤器,并且把数据库恢复到调用ApplyRange ( ) 前的状态,可以调用 T Ta b l e 组件的 C a n c e l R a n g e ( ) 方法,代码如下:2. 开发 C/S 应用程序摘自 DElPHI5 开发人员指南第 29 章2.1 为什么要采用客户/服务器结构2.2 客户/服务器体系结构2.3 客户/服务器模型2.4 客户/服务器与桌面数据库开发的比较2.4.1 面

26、向集合与面向记录客户程序并不是像桌面数据库程序那样直接面对数据库表, 而只是面对数据的子集。 客户程序在向服务器请求数据时,得到的数据可能是由一个或多个表中的字段构成的, 而请求是通过结构化查询语言(SQL )实现的。通过SQL,客户端可以限制从服务器返回的记录数。客户端通过S QL 语句从服务器上得到结果是服务器上的数据的一个子集。 这一点很重要, 因为对于桌面数据库应用程序来说, 它通过网络所得到是整个数据库表。 显然 , 数据库表越大, 网络的流量就越大。 客户 /服务器系统则不同 , 它只通过网络传送客户请求的数据, 因而网络流量较小 , 对网络的要求也较低。这个区别也影响了对S Q

27、L 数据集的浏览性。例如第一条、最后一条、下一条和上一 条记录等概念,对基于 S Q L 的数据集来说不是固有的。尤其是当查询结果是由多个数据 库表组成的情况下更是如此。许多 SQL 服务器提供了可翻滚的指针,用于浏览 SQL 结 果集。尽管如此,这与桌面数据库的浏览还是不同的,因为后者直接针对数据库表进行浏览。2.4.2 数据安全SQ L 数据库处理数据安全的方式与桌面数据库是不同的。 SQ L 数据库不仅可以对数据库进行口令验证,而且还能够针对特定的数据库对象进行限制,包括视图、数据库表和存储过程等。这意味着用户访问能够在服务器端定义,来基于用户的需要显示数据。通常, SQ L 数据库允许

28、通过G RANT 或 R EVO KE 命令向一个用户或一组用户授 予或收回权限。因此,可以在 S Q L 数据库中定义一组用户。这些权限可以应用于任何一 种已经提 到的数据库对象。2.4.3 记录锁定方法锁定是一种机制,使得多个用户可以对同一个数据库提交并发的 SQ L 事务。锁定级别有多种,不同的服务器有不同的级别。表一级的锁定主要用于限制对一个正在处理事务的数据库表的访问。尽管这种方式 允许并行的处理,但这种锁定机制速度很慢,因为多个用户往往要共享同一个表。页面级锁定是一种改进的锁定技术。用这种技术, 服务器可以把数据的某一块锁定在磁盘上, 也就是所谓的页面。当一个事务正在对某页进行处理

29、时,其他事务就不能更新该页上的 数据。由于数据往往分布在数百个页面上,因此多个事务同时操作同一个页面的可能性 很小。有些服务器还提供了记录级的锁定机制,能够锁定数据库表中的某一行。不过,这样会大大增加锁定信息的维护工作。桌面数据库采用所谓的保守或明确的锁定策略。这意味着,无法改变那些当前正在被其他用户更新的记录。如果试图访问这样的记录,将会出错,错误信息提示除非先前 那个用户释 放该记录,否则无法访问。S Q L 数据库采用所谓的优化锁定策略。这种技术并不限制访问当前正在被其他用户 访问的记录,可以照常对它进行编辑,并请求服务器保存修改后的数据。不过,在记录 被保存之前,首先会与服务器中的备份

30、进行比较,因为在查看和修改这条记录的同时, 它可能已被其他用户更新。如果该记录已被其他用户修改,则会导致一个错误,提示在 取得记录后,它已经被更新。 作为一个开发人员,在设计客户程序时应该考虑到这一点, 客户 / 服务器程序尤其要注意到这种情况,而在桌面数据库中就不会发生。2.4.4 数据完整性对于 S Q L 数据库,可以对服务器中的数据进行更健壮的完整性约束。尽管桌面数据库也内建了完整性验证的功能,但需要在应用程序的代码中定义一些业务规则。相对而 言, SQL数据库允许在服务器端定义这些规则。这一点的好处是,不仅可以强制所有 的客户端程序都接受同一套规则的约束,而且可以集中维护这些规则。完

31、整性约束是在服务器上创建数据库表时定义的,完整性约束包括有效性、唯一性 和参照性。完整性约束也可以在S Q L 存储过程中定义。例如,在处理一个订单之前,可 以先检查顾客的信用。2.4.5 面向事务S Q L 数据库是面向事务的。这意味着,对数据库的修改不是像桌面数据库那样直接针对数据库表进行的,而是由客户请求服务器进行修改,服务器用一个事务来完成这一 批操作。为了确保对数据库的修改能够有效,必须完整地提交事务。 如果事务中的任何 一个操作失败,整个事务就会被回滚 ,换句话说,就是放弃。事务能够保证服务器上数据的一致性。还是以前面提到过的存货系统为例,当顾客提交了一份订单后, O R D E

32、R S 表必须更新。另外, PA RT S 表也必须相应地把零件数减少。如果因为某种原因,系统在更新O R D E R S 表和 PA RT S 表之间出错, PA RT S 表 中的零件数就不能反映实际情况。但是,如果把整个操作放在一个事务中,除非整个事 务正确地提交, 否则,没有一个表会有任何改变。在 Delphi 5 中,对于事务既可以在服务器层进行控制,也可以在客户层进行控制。2.5 SQL 在客户/服务器开发中的角色2.6 Delphi 客户/服务器开发Delphi 5 提供了一些数据库对象组件,它们封装了 B D E 的功能。这样,开发数据库应用程序就不必知道B D E 的功能。其

33、次, Delphi 5 提供了数据感知组件可以与数据访 问组件彼此通信,这样,建立数据库应用程序的界面就变得简单。 SQLLinks 为连接 Or a c I e 、 S y b a s e 、 I n f o r m i x 、 Microsoft SQL Server 、 D B 2 和 I n t e r B a s e 提供了专门的驱动 程序Delphi 5 还包含了 Ml DA S 技术,“ M I DA S : Multitier Distributed Application Services Suite ”。最后, D e l p h i 允许使用 CORBA(CommaOnb

34、ject Request Broker Architecture) 来开发分布式应用程序。 C O R B A 规范已经被OMG(Object ManagementGroup) 采用。通过C O R B A 技术,可以创建面向对象的分布式应用程序2.7 服务器:后端设计2.8 客户:前端开发2.8.1 使用 TDatabase 组件T D a t a b s e 组件可以更有效地控制数据库的连接,包括: 建立一个永久的数据库连 接。 覆盖默认的服务器登录。 创建应用程序级的 B D E 别名。 控制事务并指定事务的隔离级别。. 应用程序级的连接使用 T D a t a b a s

35、 e 组件的原因之一是,可以通过它建立一个应用程序级的别名。 与 B D E 配置程序建立的别名不同的是, T Da t a b ase 组件建立的别名只在本项目 中有效。如 果要与其他应用程序共享这个别名,可以把 T D a t a b a s e 组件放到可共 享的数据模块( TD a t a M o d u l e ) 中,然后把数据模块放到对象库中,这样,其他应用程序就可以使用它了。要建立一个应用程序级的别名,可以设置T D a t a b a se . D a t a b a s e N a m e 属性。至于T D a t a b a s e 要连接的数据库的 B D E 别 名则

36、由 TD a t a b a s e . A l i a s N a m e属性来指定。. 安全控制T D a t a b a s e 通过控制用户的登录过程来限制用户对服务器数据的访问。在登录时,用户必须给出合法的用户名和口令才能访问数据。默认情况下,当试图连接数据库时,会打开一个标准的对话框。处理登录有几种方式。首先,完全可以跳过登录,让用户不需登录就可以访问服务器数据。其次,可以根据需要调出几种不同的登录对话框,以便在将用户名和口令传给服务器进行正常的检查之前进行你自己的合法性检查。最后,可以允许用户在不关闭应 用程序的情况下退出再重新登录。下面将详细介绍这些技术。2.8.

37、1.2.1 自动登录不让登录对话框出来如果不想出现登录对话框,必须设置T D a t a b a s e 的下列属性:A l i a s N a m e 设为一个已有的用 B D E 配置工具定义的 B D E 别名,通常与T Ta b l e 、 T Q u e r y 组件的 A l i a s 属性相同。D a t a b a s e N a m e 设为一个应用程序级的别名,这个别名代表T Ta b le 、 T Q u e r y 或 T S t o r e P r o c 组件要访问的数据库。这些组件将使用该值作为它们的 A l i a s 属性值。L o g i n P r o

38、m p t 设为 F a l s e ,这样, T D a t a b a s e 组件将从 P a r a m s 属性中获取用户名和口令。 P a r a m s 给出用户名和口令。为此,必 须打开一个字符串编辑器来设置这些值。设置了这些属性后,必须把T Ta b l e 、 T Q u e r y 或 T S to re P r o c的 A l i a s 属性值设为 T D a t a b a s e 的 D a t a b a s e -N a m e 属性值, 这样,就把这些数据集组件与 T D a t a b a s e连接起来。现在,可以把T D a t a b a s e

39、. C o n n e c t e d 的属性设为 Tr u e 。这样,当应用程序连接到服务器时,将不提示输入用户名和口令,因为 P a r a m s 属性中已经给出了用户名和口令。.2 自定义的登录对话框在某些场合,可能需要为用户提供自定义的登录对话框。例如,你可能想提示用户 在对话框中输入除了用户名和口令之外的附加信息,或者希望在程序开始时能出现更漂 亮的登录对话框,而不是默认的那种。无论是何种情况,处理都非常简单。首先,把 T D a t a b a s e . L o g i n P r o m p t属性设为 Tr u e ,这样就不会显示默认的登录对话框 , 并保

40、证触发 0 n L o g i n 事件。不过,现在不要通过P a r a m s 属性提供用户名和口令,而要编写 处理 T Dat a b as e . 0 n L o g i n事件的处理过程 。这个事件处理过程在T D a t a ba s e . C o n n e c t e d 属性和 T D a t a b a s e . L o g i n P r o m pt 被设为 Tr u e 时被调用。下面的函数自定义了一个登录窗口,并返回用户名和密码:.3 从当前会话退出. 事务控制的有关属性和方法来处理事用 Delphi 5 编写的客户程序可以通过T D

41、 a t a b a s e务。下面将介绍怎样在Delphi 5 程序中处理事务。.1 隐式和显式的事务控制Delphi 5 既可以隐式又可以显式地处理事务,默认是隐式的。隐式的事务是以逐行的方式开始和提交的。这意味着,当调用 P o s t 方法或 P o s t 方法 被VCL的代码自动调用时,由于是逐行处理的,因此可能导致网络流量增加,从而 降低效 率。显式的事务处理又分下面两种方式。一种方式是调用 T D a t a b a s e 组件的 S t a r t Tr a n s a c t i o n ( )、C o m m i t () 或 R o II B a c k

42、 () 等方法;另一种方式是通过T Q u e r y 组件的直通 ( p a s s - t h r o u g h ) S Q L 命令来实现的,由于显式事务的网络流量较小,而且代码较安全,建议采用这种方式。.2 处理事务T D a t a b a s e 的方法中有三个是与数据库事务有关的,分别是: S t a r t Trans a c t i o n ( )、 C o m m i t () 和 R o l l B a c k ()。S t a r t Tr a n s a c t i o n ( ) 启动一个事务 ,隔离级别由 T D a t a b a s e . T

43、r a n s I s o l a t i o n属性指定。在调用 S t a r t Tr a n -s ac t i o n ( ) 之后对数据库所做的任何修改都成为事务的一部分。如果对数据库的所有修改都成功,则调用 T D a t a b a s e . C o m m i t ( ) 方法把所有修改一次保存到数据库中。反之,如果 发生了错误,则调用 T D a t a b a s e . R o l l B a c k ( )方法来取消所有的修改。.3 SQL 直通模式S Q L 直通 (p a s s - t h r o u g h )模式能够使Delphi 5 数据库

44、应用程序与B DE 共享到数据库服务器的连接。 Delphi 5 的程序中如果调用了 BDE API 则可能需要使用 B D E 连接。直通模式是在 B D E 配置工具中设置的。这种模式有三个选项:SHARED AUTO C O M M I 以逐行方式处理数据库事务,主要用于桌面数据库应 用程序。在客户 / 服务器环境下, 这将导致网络流量增加, 因此不推荐这个选项, 但 这是 Delphi 5 应用程序的默认选项。SHARED NOAUTO C O M M I T Delphi 5 程序必须通过调用 T D a t a b a s e 的 S t a r t Tr a n s a c t

45、i o n ( ) 、 C o m m i t ( ) 和 R o l l B a c k ( ) 方法来显式地启动、 提交和回滚事务。NOT SHARED B D 和 T Q u e r y 组件提交的直通 S Q L 语句不共享同一个连接这意味着, SQL 代码可以不受 BDE 功能的限制,可以发挥服务器的特性。如果不想使用直通式 SQL 但又想对事务进行更多的控制,可以把这个选项设为 SHARED NOAUTOC O M M 并自行处理事务。在大多数情况下,这种模式是可以的。但是,在多用户环境下,如果某条记录需要频繁地更新,则可能发生冲突。.4 隔离级别隔离级别是指一个事务

46、对其他事务正在访问的数据具有怎样的可见性。 T D a t a b a s e .Tr a n s I s o l a t i o n 属性用于指定一个事务的隔离级别。对于 Tr a n sI s o l a t i o n 属性,可以有三种取值,分别代表三种隔离级别:t i D i r R e a d 最低的隔离级别。具有该级别的事务可以读取其他事务正在修改但还没有提交的数据。t i R e a d C o m m i t t e d这是默认的隔离级别。具有该级别的事务只能读取那些已被其他事务提交的数据。t i R e p e a t a b l e R e a d这是最高的隔离级别。具有这

47、种隔离级别的事务无法读到另一个事务正在读取的数据。不同的服务器所支持的隔离级别也可能不同。 Delphi 5 通常使用 t i R e a d C o m m i t t e d 级别,除非服务器不支持该级别。2.8.2 TQuery 比 TTable 优秀有人认为开发客户 / 服务器结构的前端与开发桌面数据库应用程序是相同或类似的, 这是 一个较为普遍的错误认识。从使用 T Ta b l e 还是 T Q u e r y 的比较中,我们可以体会到这种区别。下面将讨 论使用T Ta b l e 组件的优缺点,分析在什么情况下应该使用它、什么情况下不应该使 用它。通过这些分析,你将会理解为什么使

48、用 T Q u e r y 组件比较好。T Ta b l e 组件能够操作整个数据库表、浏览前后的记录或者转到某个特定的记 录。不过,这些概念对SQL 数据库服务器来说则是不适用的。关系型数据库是 以数据集的形式被访问的。因此, S QL 数据库中没有下一条记录、前一条记录和后一条记录等概念。而在T Ta b l e 组件中,这些概念是非常普遍的。尽管有 些 SQL 数据库提供了可滚动的指针,但这不是标准的,当我们通过T Ta b l e 组件操作 S Q L 数据库时,最重要的一点就是, 通过 T Ta b le组件发出的数据库操作命令必须转换为 SQ L 代码才能被SQ L 数据库识别和

49、执行。这不仅限制了对数据库的访问,而且也大大降低了效率。虽然 T Ta b l e 的 F i n d K e y () 方法能够搜索记录,但对于 S Q L 数据库来说此方法是有限制的。首先, F i n d K e y ( ) 只能基于定义了索引的字段进行搜索,而TQue r y 则没有这个限制,因为它是用 S Q L 来查询记录的。尽管TTable.FindKey() 最终还是用 S E L E C T 命令来对数据库表进行操作的,但是, 使 用 F i n d K e y () 得到的结果集中包含了所有的字段,即使通过T Ta b l e的字段编辑器只选择了其中部分字段2.8.3 使用

50、 TQuery 组件3使用ADO摘自 Master Delphi7 第 15 章3.1 Microsoft 数据访问组件 (MDAC)3.2 使用dbGo 组件3.3 使用Jet 引擎3.4 光标AD 喋合有两个基础属性会对程序产生基础性的影响, 并且不可分割的相互链接在一起,它们是: CursorLocation 和 CursorType3.4.1 光标位置CursorLocation 属性运行程序员来指定谁控制数据的提取和更新,有两个选择:客户机( clUseClient )和服务器 ( clUseServer ) 。所作的选择会影响数据集合的功能、 性能和可扩张 性。 客户

51、端光标 ( clUseClient )客户端光标由 ADO Cursor Engine 负责管理,当数据集打开的时候数据从服务器提取到客户端,并保存在内存中,由 ADO Cursor Engine 管理更新和操作 服务器端光标( clUseServer )3.4.2 光标类型 只向前光标 静态光标 键集光标 动态光标3.4.3 要求与结果3.4.4 无记录计数3.4.5 客户端索引IndexFieldName , AD (不从数据源读数,而是在内存中完成的。3.4.6 复制Clone 方法可以复制任意的 AD (数据集合。复

52、制不会影响到最初的地副本,它们拥有 自 己的记录指针和其它状态信息 , 并且可以拥有不同的 Active 记录3.5 事务处理AD (的事务处理被ADOConnectior ffl 件控制,使用 BeginTrasaction 、CommitTrasaction 、 RollbackTrasaction3.5.1 嵌套事务3.5.2 ADOConnection 属性3.5.3 锁定类型ADO 支持四种不同的方法来锁定用于更新的数据( LockType 有 4 种属性),它们是:ItReadO nl y,ltPessimistic,ltOptimistic,ltBatchOptimistic3.

53、5.3.1 ltReadO nly:指定数据是只读的,并且不能更新 ltPessimistic 消极锁定:消极锁定假设用户将有很大的可能性会同时更新相同的记录,并出现冲突。为防止 这样的冲突,当编辑开始时记录将被锁定,并一直持续到更新完成或者取消操作为止。 第二个试图编辑相同记录的用户将不能成功锁定记录,并会收到一条“不能更新,当前 记录已被锁定”的异常。优点:用户可以知道他们是否可以开始编辑一条记录, 以及是否能成功的保存他们的更新缺点:用户在锁定与接触锁定的时间上需要控制, 防止用户开始编辑一条记录就离开了,而使此记录一直被锁定。 常用 TTime 设备,在键盘与鼠标休眠一定

54、时间 后解除锁定。 ItOptiimstic 消极锁定必须使用一个服务器端的光标。3.6 更新数据3.6.1 联合查询 DataSet 的更新AD (支持批更新,并且AD (的连接是天生可以“更新的”。在一个AD 连接中,每个字段对象都知道它属于哪个数据库表。例如由表 Products 和表 Supplier 连接查询生产ADODataSetJointData ,如果更新的字 段属于 Products 表,则会生成一条针对Products 表的 SQLUpdate 语句。如果更新2 个字段 分别属于 Products 表和 Supplier 表,则会生产2 条分别针对Produts 表和 Su

55、pplier 表的 SQLUpdate 语句ADO 军决方案的最大问题是删除一个连接的一行时,操作将会失败。假如用户只想删 除Products 表的数据,可以用下面代码来指定删除只针对Products 表ADOQuery1.Properties Unique Table ' .Value:= ' Products ' ;AdoQuery3.6.2 批更新使用批更新的时候,对记录做的任何修改都在内存中进行,然后将整批的修改作为 一个操 作来提交,其用法如下:在打开数据集合前,将 LockType 设为 ItBatchOptimistic 将 CursorLocation

56、设为clUseClient ,因为批更新是由 AD( 的 ADO Cursor Engine 管理的。然后所有的修改作为增量,在内存中进行使用 UpdateBatch, 更新永久有效使用 Can cleBatch 或 Can cleUpdate 放弃整批的更新3.6.3 ADO 的其它重要属性 UpdateStatusUpdateStatus 用于识别记录的状态(插入、更新、删除或未修改 ) ,它特别适用于在 Grid 中用不同颜色来突出记录 UpdatesPendingADO 数据集的 UpdatesPending 属性,在数据集已经修改但是还没有应用的时候为True ,这在窗体的 OnCloseQuery 事件中用于提示还有未保存的数据:Procedure TForm1.FormCloseQuery(Sender:TObject;var CanClose :Boolean)BeginCanClose:=True;If ADODataSet1.UpdatesPending thenCanClose:=Me

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论