发信人: atong (sut), 信区: BorlandDev
标  题: 深入delphi编程(转5)
发信站: 哈工大紫丁香 (Wed Jul  3 20:05:29 2002) , 转信

2、数据库
  
  在相对枯燥的理论之后,我们终于要开始接触到一些比较激动人心的实际应用了。
  数据库编程是delphi最强大的优势之一,恐怕也很少有delphi程序员没有接触过数据
库编程的。delphi独特的data-aware构件,让很多初识delphi的人为之目瞪口呆。不需要
写任何代码,在几分钟之内就可以做出一个相当精巧的数据库程序,而且在开发期就可以
看到运行期的结果,这真是不可思议啊!但是,delphi强大无比的数据库开发能力,决不
仅仅限于用几个构件操纵一下dbf或是access数据库而已。你所看到只是冰山一角。让我们
仔细说来。
  数据库虽然家族庞大,但一般来说可以分为两种:文件型数据库和c/s型数据库。下面
分别讨论。
  
  2.1 文件型数据库
  所谓文件型数据库,顾名思义,是基于文件的(file-based),数据被按照一定格式
储存在磁盘里,使用时由应用程序通过相应的驱动程序甚至直接对数据文件进行读取 。
也就是说,这种数据库的访问方式是被动式的,只要了解其文件格式,任何程序都可以直
接读取,这样就使得它的安全性相当糟糕。同时,在蓬勃兴起的网络应用,文件型数据库
更是难有用武之地:效率低下,不支持很多sql命令,不支持视图、触发器、存储过程等高
级功能,等等。这些特点决定了它不适合大型的工程。
  最为大家所熟悉的文件型数据库可能就是dbf(dbase/foxbase/foxpro)数据库,在d
os时代风靡一时,相信很多人都有过抱着一本手册苦背foxbase命令的回忆吧!其特点是,
每个table或index都是一个独立的文件,使用相当简单,性能还可以,安全性非常的差,
但应用非常广泛(主要是dos时代遗留下来的,哪个单位没有两个用这种东东编出来的老古
董程序呢?)。它在今天还能占有一席之地,其主要原因之一是,正因为简单和使用广泛
,使得对它的访问是最容易的,甚至根本无需第三方的接口,就可直接对其进行字节级的
读取 。
  除此之外,还有著名的access数据库。这是ms office里的构件之一,和dbf数据库不
同,所有的文件都被整合在一个.mdb文件中,这样就避免了数据库变大之后管理上带来的
麻烦。同时它还提供密码保护功能,安全性比dbf数据库要好很多。access数据库除了一般
的文本数据之外,还擅长于对多媒体数据的处理,在对声音、图像乃至基于ole的对象进行
处理时,令dbf数据库望尘莫及。随着微软战略的步步胜利,access数据库也不断发展,凭
借着优秀的性能和与ms office的无缝结合,早已超越dbase系列,成为现今最强大的文件
型数据库了。
  delphi中附带的paradox也是一种文件型数据库。它是inprise公司自己的产品。因此
和inprise的系列开发工具配合得很不错。它支持密码保护,支持标准的sql,性能也还不
错,但是应用就不那么广泛了。和dbf数据库一样,它的每一个table都是一个独立的文件
,因此也有同样的管理问题。
  上文说到可以对文件型数据库直接读取,但实际编程中很少有人这么做。因为再简单
的数据库其实也是相当复杂的,一步步分析它的格式,从底层实现所有的数据库应用,如
果都要程序员去写的话,可能会把人累死。所以数据库的开发商将这些访问代码封装起来
,向程序员开放,程序员只需要调用相应的接口就可以了。
  以dbf为例,使用dbase/foxbase/foxpro系列开发工具,可以用它自己的语法开发出应
用程序。其中对dbf文件的具体操作被封装了。对于access数据库,微软公布了一个dao(
database access object),由一系列的dll文件组成,封装了对.mdb文件的访问。使用v
b的读者可能对dao比较熟悉,只要在vb中嵌入dao对象,就可以非常方便地访问access数据
库了。odbc(open database connection,开放数据库互连)也是一种封装,用意在于向
开发人员提供一个统一的接口,通过这个接口可以访问任何支持odbc的数据库,只要该数
据库提供了相应的odbc驱动。从这一点上来说,odbc是一种更加高级的封装。目前几乎所
有的主流的数据库都能被odbc所支持。打开你的windows的控制面板,就可以看到odbc的图
标。
  用delphi写数据库程序的人免不了要同bde打交道。bde(borland dasebase engine,
borland数据库引擎)是一个和odbc类似的东西,borland/inprise本来企图用它来统一数
据库接口。但后来inprise在和微软的战争中败下阵来(odbc是微软搞出来的),它又不肯
放弃bde,而是将其捆绑在delphi/c++ builder系列开发工具中,结果好象变成这些开发工
具的一种附属品了。
  用bde开发数据库程序相当容易。许多delphi教科书在写到数据库开发这一章时,总是
告诉你先在bde中为某个dbf或paradox数据库设置一个别名,然后往窗体上放一个ttable构
件,然后将其databasename指向相应的别名……然后,这个数据库中某个表的内容就在相
应的data-aware构件中显示出来了。但是它们具体是怎么工作的呢?
  delphi对数据库进行访问时,事实上通过了很多层次的连接。如下图:
  
  图1
  dataaware构件-datasource构件-dataset构件-bde-数据库
  
  从这个图可以看出,bde负责与具体的数据库打交道,而dataset构件与bde相连,dat
asource构件与dataset构件相连,最后才连接到显示具体数据的data-aware构件。在delp
hi的构件面板上,data access页面中的构件一般属于dataset构件,例如ttable、tquery
,只要指定它们的databasename属性,就可以将它们与某个数据库建立连接。在data con
trol页面中的构件一般是data-aware构件,例如tdbgrid,tdbedit,tdbimage。它们的作
用看上去与一般的delphi构件相似,不同之处在于,可以通过一个datasource构件作为中
介,与dataset构件相连,并自动显示相应的数据。
  用delphi的数据库构件建立一个应用程序是如此之方便,但是如果深入下去,会发现
事情并不简单。你可以尝试自己编写代码,访问数据库中字段,而不是通过data-aware构
件由用户来编辑。如何做到这一点呢?秘密在于field构件。
  可以说,field构件是delphi数据库应用程序的基础 。当打开一个dataset构件时,
相应的数据会被读取,并储存在ttable或tquery构件的fields属性中。这个属性被定义为
field数组。通过直接访问数组,可以使用它们,例如:
  
  table1.fields[0].asinteger;
  
  这段代码访问了table1中当前记录的第一个字段,该字段的类型为integer。
  也可以通过使用fieldbyname属性来使用它们:
  
  table1.fieldbyname('last name').asstring;
  
  这段代码访问了table1中当前记录的名为last name的字段,该字段的类型为string。

  事实上,data-aware构件就是通过访问dataset构件的fields属性来使用数据的。弄明
白了这一点之后,你自己也可以尝试改写一个常规的显示构件,使之具有data-aware的性
质。其实,大多数使用delphi的数据库高手并不喜欢使用data-aware构件,因为data-awa
re构件远不用常规的构件来得灵活。dataset构件除了fields属性之外,还具有数目众多的
特殊属性、方法和事件,足以应付从小型文本数据库到大型网络数据库的所有应用。本文
不拟一一讨论它们,如果读者能将它们的运用烂熟于心的话,可以说应付数据库编程就不
会有多大问题了。
  请将注意力再次集中到图1。在图1的最后一环,可以看到bde连接到了具体的数据库。
其实,在这一环中,也是有几个层次的。理论上来说,bde可以连接任何类型的数据库。对
于一些比较简单的数据库,例如ascii(纯文本型的数据库)、dbase以及delphi自己的pa
radox,bde可以直接访问。另外它也可以通过一些相应的驱动,访问特定的数据库,例如
通过dao访问access数据库。对于不能直接支持的数据库,bde还可以连接到odbc,通过od
bc进行访问,虽然这样效率比较低。
  这种性质决定了bde是一个相当庞大的东西。使用了bde的delphi程序,必须有bde才能
工作,所以必须同bde一起发布。这样往往造成这样一种情况:只有几百k的应用程序,在
将整个bde加入之后,体积将近10m!这对于以轻薄短小为长的文件型数据库,简直是一个
致命的弱点。而且由于bde要兼容太多的数据库,本身也有不稳定的毛病,往往出现令人头
疼的问题。同时,通过安装程序安装bde驱动和设置数据库别名也是一件很麻烦的事情,这
一切使得bde在delphi程序员中很不受欢迎。在网上的delphi技术论坛里,经常可以看到对
bde的一片咒骂之声……那么,有什么办法可以绕过bde吗?
  有的。目前来说,至少有以下三种方法:
  (1) 使用第三方构件。
  inprise自己也很早就意识到了bde的问题,虽然他们不肯放弃bde,但是从delphi3起
,仍然对程序员提供了一个不错的选择:创建自定义的dataset构件。delphi的开发者们把
所有有关bde的东西从tdataset类中移走,放入了新的tbdedataset类(tbdedataset类是t
dataset类的子类)。tdataset类被重新构造,其核心功能被虚拟化。因此,你只需要从t
dataset类派生一个自己的新类,并重载一些指定的虚拟方法(用以访问具体的数据库),
你就可以得到一个自己的dataset构件。它与bde完全无关,但可以象delphi自己的datase
t构件一样被使用,例如,访问其fields属性,乃至与delphi的data-aware构件一起工作!

  于是出现了大量的第三方构件,它们可以访问某种特定的数据库。下面是一些比较常
见的访问文件型数据库或odbc的第三方构件:
  
  
  表2

名称 支持的数据库类型 
diamond access 
halcyon dbase/foxpro 
apollo dbase/foxpro 
modbc 任何odbc数据库 
odbc express 任何odbc数据库 



  
  这些控件被广泛使用,在国内,就作者所知,财智家庭理财软件使用了diamond,而“
追捕”(一个显示指定ip的地址位置的共享软件)使用了halcyon。在使用这些第三方构件
之后,软件终于可以“轻装上阵”,再也不用为bde头疼了。
  (2) 使用ado。
  在delphi5中,inprise终于提供了一个比较彻底的解决方法,那就是ado构件。从原理
上来说,ado与上述的第三方构件并无多大区别,只是它是inprise官方开发的;同时,它
连接的不是某个具体的数据库,而是微软提供的ado对象。
  ado(activex data object,activex数据对象)是微软提出的新标准,从理论上来,
能够支持任何类型的数据库(甚至包括流式数据)。微软力图将它树为新的统一数据库接
口,吹嘘了它的许多优点。inprise一直是微软不共戴天的竞争对手,对微软的标准嗤之以
鼻(bde即是一例),但是由于种种原因,inprise终于承认了ado。平心而论,用ado来取
代bde的确是一个不错的解决方案,而且在delphi中使用ado也相当方便。从形势看,ado应
该是未来的方向。但是,ado本身也是相当大的。
  (3) 从最底层开发一个完整的数据库引擎。
  这是最彻底的办法。彻底抛弃delphi的数据库支持,从字节开始,开发自己的数据库
。这种方法有其好处:第一,不用考虑兼容性问题,例如不用去考虑用户的数据库文件是
access 97格式还是access 2000格式的;第二,可以在性能上达到最充分的优化,因为不
需要通过任何通用接口,而是直接对磁盘文件进行操作,这对于一些对性能要求苛刻的程
序是很有用的;第三,能够最大限度地减少冗余代码,因为这种数据库往往是特定格式的
,而且只需要执行一些特定的操作,访问代码当然要比通用数据库精简得多。但这种方法
的负面问题也显而易见,那就是庞大的工作量。再简单的数据库也是相当复杂的,从最底
层实现一个完整的数据库引擎,往往需要几千行代码,以及耐心和经验。
  虽然听起来有些极端,但这样做的也不乏其人。著名的foxmail就是使用了自定义的数
据库格式来储存信件、地址本等有关信息。另一个共享软件“电子书库”也使用了自定义
的.srm格式。作者开发的icompanion(网络伴侣)也是使用自定义格式来储存网络记录的

  限于篇幅,这里就不再对具体的程序进行详细的分析了。要补充的一点是,作者曾使
用diamond开发过rich explorer,这是一个专门用于浏览著名的大富翁论坛的离线数据库
(access格式)的阅读器。在作者的主页上,可以找到rich explorer的全部源代码,它完
整地展示了一个使用第三方构件访问特定数据库的程序(没有使用data-aware控件),代
码也比较简单,适合于初学者分析,有心的读者不妨作为参考。
  

--

※ 来源:.哈工大紫丁香 http://bbs.hit.edu.cn [FROM: 202.118.239.3]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.790毫秒