深入Delphi编程
这些控件被广泛使用,在国内,就作者所知,财智家庭理财软件使用了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控件),代码也比较简单,适合于初学者分析,有心的读者不妨作为参考。
2.2 C/S型数据库
C/S(Client/Server,客户机/服务器)型数据库是当前数据库应用的主流。
与文件型数据库不同的是,C/S型数据库应用程序由两个部分组成:服务器和客户机。服务器指数据库管理系统(Database Manage System,DBMS),用于描述、管理和维护数据库的程序系统,是数据库系统核心组成部分,对数据库进行统一的管理和控制。客户机则将用户的需求送交到服务器,再从服务器返回数据给用户。
C/S型数据库非常适合于网络应用,可以同时被多个用户所访问,并赋予不同的用户以不同的安全权限。C/S型数据库支持的数据量一般比文件型数据库大得多,还支持分布式的数据库(即同一数据库的数据库位于多台服务器上)。同时,C/S型数据库一般都能完善地支持SQL语言(所以也被称作SQL数据库)。这些特性决定了C/S型数据库适合于高端应用。
常见的C/S型数据库有著名的Oracle, Sybase, Informix, 微软的Microsoft SQL
server, IEM的DB2,以及Delphi自带的InterBase,等等。
C/S型数据库涉及到非常多的高级特性,是Delphi中,也是整个计算机领域中最大的应用之一。由于本期附录中已有专文讨论,本文就不拟详细介绍了。
随着技术的不断更新,C/S型的结构也开始逐渐被多层(Multi-Tiered)数据库模型所取代。
上面说到,C/S型数据库程序由服务器和客户机两个部分组成,因此被称为双层(two-tiered)模型。文件型数据库程序则被称为单层(single-tiered)模型。单层模型是最原始的数据库模型。后来程序员们将数据库转移到一个强大的中央服务器上,让它为多个功能较弱的客户机提供服务,这样双层模型出现了。双层模型在金融、电力、通信等领域被广泛使用,极大地推动了网络数据库的发展。但是,双层模型也逐渐暴露出其不足的一面。在这种情况下,出现了三层模型:应用程序中的数据模块部分被分离出来,转移到一个单独的服务器上,成为独立的一层。三层和三层以上的模型,统称为多层模型。
` 简言之,三层模型由以下三个层次组成:
客户机-应用程序服务器-数据库服务器
用户的请求首先通过客户机向应用程序服务器发出,应用程序服务器再向数据库服务器发出具体的数据访问命令(一般是SQL),数据库服务器返回的数据被应用程序服务器重新组织之后返回给客户机。
可以看出,三层模型是双层模型的扩展。目前我们无需了解三层模型的所有技术细节,以及它对于双层模型的优势,只需要大致理解这个模型的结构就可以了。
B/S模型无疑是当前最为流行的多层数据库模型之一。也许你已经听说过B/S这个名词,它是Brower/Server(浏览器/服务器)的缩写。Brower是指IE/Netscape这样的浏览器,Server包括数据库服务器和应用程序服务器。用户通过浏览器发出某个请求,通过应用程序服务器-数据库服务器之间一系列复杂的操作之后,返回相应的Html页面给浏览器。
是不是觉得十分熟悉?对了,其实这就是大家再熟悉不过的Internet上的WEB数据库,当然它也可以用于局域网。它实际上可以说是一种最常见的多层模型。
在对数据库的发展进行回顾之后,我们终于赶上了最流行的步伐。但是,也许有人在这里却感到泄气了。因为他听说现在的WEB数据库编程,是Perl、ASP、PHP、JAVA这些语言的天下。难道我们一直忠实追随的Delphi,在面对当代最流行的Web数据库的时候,竟然面临淘汰的命运?
不,不是的。其实Delphi对Web数据库的开发提供了非常良好的支持,特别是依据强大的数据库支持和可视化编视的特点,它有着其他语言不可比拟的优势。
下面的内容将集中于用Delphi开发Web数据库。
首先要从Web本身讲起。平时我们浏览的Web页面,一般可以分为两种。一种是静态页面,这种页面是文本格式的html文件。但是,要响应用户的不同需求,从而反馈给用户不同的页面,就必须使用动态页面技术了。例如,根据用户输入的名字,迅速在数据库中查找到相应的数据,并动态生成一个页面返回给用户。
怎样实现动态页面技术呢?最早的一种方法是CGI(Common Gateway Interface,通用网关接口)。这种接口允许浏览器发送和接收数据,并且基于应用程序的命令行进行输入和输出。当浏览器发出指向应用程序的请求时,Web服务器会自动启动该程序,并在浏览器和应用程序之间传递输入和输出的数据。实现CGI的语言有很多种,其中比较流行的是Perl。另外,还有一种特殊的WinCGI。WinCGI与普通CGI的区别是,它通过INI文件来代替命令行参数作为输入输出,这主要是为Visual Basic设计的,因为VB不能访问环境变量。Delphi对这两种CGI都提供了很好的支持,可以编写出非常复杂的CGI程序。
第二种方法是使用Web服务器内置的API接口。用这种接口编写出来的Dll文件,被Web服务器装载到自己的内存空间中,当服务器接收到相应的页面请求时,它将启动一个新的线程来执行Dll中的相应代码。由于不需要执行外部的EXE文件,这种程序的速度非常快。这种API主要有ISAPI(Internet Server API)和NSAPI(Netscape Server API),其中前者已经成为事实上的标准。Delphi对这两种API也提供了很好的支持。提得一提的是,Delphi的C/S版提供了一个通用的类框架,消除了CGI、WinCGI和ISAPI之间的区别,这样,我们可以轻松地将一个应用程序在这三者之间转换。
还有一种是Web服务器内置的脚本语言,可以被简单地嵌入html文件,通过Web服务器的解释执行来产生动态页面。著名的ASP、PHP、JSP都属于此类。这看起来和Delphi没有什么关系,但事实上,Delphi也能提供对ASP的强力支持!ASP的初学者可能会把注意力都集中在它的脚本语言上,其实ASP是由三部分组成的:脚本、组件和html。光是掌握脚本和ASP原有的组件特性是远远不够的,只有自行开发组件,才能实现真正复杂、高效的应用。Delphi就非常适合开发这种组件。国内著名大富翁论坛,就是基于Delphi+ASP的成功例子,同时它还公布了所有的源代码,可供借鉴。
让我们先建立一个程序。这个程序和以往的Delphi不同,要求删除所有的窗体和多余的代码,最后只剩下这么一段:
program CgiDate;
{$APPTYPE CONSOLE} //这行编译器指令表示这是一个控制台程序,不需要窗体,在终端窗口中输出
uses
sysutils;
begin
writeln(‘HTTP/1.0 200 OK’);
writeln(‘CONTENT-TYPE: TEXT/HTML’);
writeln;
writeln(‘
writeln(‘
writeln(‘‘);
writeln(‘
Time at this site
‘);
writeln(‘
‘);
writeln(‘
‘);
writeln(formatdatatime(‘”Today is ” dddd,mmmm d,yyyy,’ + ‘”
and the time is “hh:mm:ss AM/PM’,now));
writeln(‘
‘);
writeln(‘
writeln(‘
‘);
writeln(‘‘);
end;
编译后,将该程序置于Web服务器下的有scripts权限的子目录中,并用浏览器访问它,就可以得到一个关于当前时间和日期的页面。
分析一下这段代码。格式很简单,都是用writeln生成标准输出。首先的两行生成html的描述,中间空一行,接下来的代码生成了一个完整的html文件。这个文件被返回给浏览器并显示出来。与静态页面不同是,有一行html文本是通过formatdatatime函数动态生成的,因此根据当前时间的不同会有不同的显示。
这就是一个最简单的CGI程序。虽然简单,但已经可以看出CGI程序的基本工作原理:通过标准输入输出产生动态的html页面。
在这个基础之上,可以方便地实现对数据库的访问,并生成相应的html。
下面是一个例子:
var:
Table1:TTable;
Begin
Showheader; // Showheader过程生成html文件的头部,代码与上例相似
Table1 := TTable.create(nil);
Try
Table1.Databasename := ‘DBDEMOS’;
Table1.tablename := ‘Employee.db’;
Table1.indexname := ‘Byname’;
Table1.open;
ShowTabindex; //显示表中的列
Finally
Table1.close;
Table1.free;
End;
Writeln(‘