18.3.4.1适化概述所谓适化就是将桌面应用转化为Client/Server应用。适化是一个很复杂的主题,这里不详细讲述。本节将介绍适化Delphi应用程序中最重要的方面。适化的主要方面有:●将数据库从桌面平台到服务器的适化●将应用程序转化为Client/Server的适化适化还需要实现从桌面环境到Client/Server环境的转化。桌面数据库和SQL服务器数据库在许多方面有不同之处。例如:●桌面数据库用于同一时刻单用户的访问,而服务器用于多用户访问●桌面数据库是面向记录的,而服务器是面向集合的●桌面数据库将每个表存储在独立的文件中,而服务器将所有的表存储在数据库中Client/Server应用必须解决更新的问题,最复杂的是联接、网络和事务控制18.3.4.2适化数据库适化数据库包含下列步骤:●在桌面数据库结构的基础上,定义服务器上的元数据●将数据从桌面转化到服务器中●解决下列问题:●数据类型差异●数据安全性和完整性●事务控制●数据访问权●数据合法性●锁定Delphi提供了两种方法适化一个数据库。●使用DatabaseDesktop工具,选择菜单Tools/Utilities/Copyto命令将数据库表从桌面方式拷贝到SQL格式●建立应用TBatchMove部件的应用程序这两种方法都可以将表结构和数据从桌面数据源转化到服务器上。依靠这些数据库,可能需要改变结果表。例如,可能想进行不同数据类型的映射。也可以将下列特征加入数据库:●完整性约束●索引●检测约束●存储过程和触发器●其它服务器特征如果用SQL脚本和服务器数据定义工具定义元数据会更有效。然后用前面介绍的两种方法转移数据。因为如果是手工定义数据库表,DatabaseDesktop和TBatchMove部件将只拷贝数据。18.3.4.3适化应用程序在理论上,设计用来访问局部数据的Delphi应用程序做很少的修改就可以访问远程服务器上的数据。如果在服务器上定义适合的数据源,你就能将应用程序指向访问它,这只需简单地改变应用程序中TTable或TQuery部件的DatabaseName属性。实际上,在访问局部和过程数据源之间有许多重要的不同之处。Client/Server应用程序必须解决大量的在桌面应用中所没有的问题。任何Delphi应用程序都能用TTable或TQuery部件访问数据。桌面应用程序通常都是使用TTable部件。当适化到SQL服务器上时,用TQuery会更有效,如果应用程序要检索大量记录,则TQuery部件要略胜一筹。如果应用程序使用统计或数学函数,那么在服务器上通过存储过程执行这些函数会更有效。因为存储过程执行更快,使用存储过程还可以减少网络负载,特别是大量行数据的函数。例如,计算大量记录的标准差:●如果该函数在客户端执行,所有的值从服务器上检索出来并送到客户端,导致网络拥塞●如果该函数在服务器端执行,则应用程序只需要服务器上的答案18.4Delphi客户/服务器应用实例分析本节中采用的实例是Delphi2.0数据库的例子CSDEMO。CSDEMO是Delphi客户/服务器编程的示例程序,它采用的数据库服务器是LocalInterBaseServer。CSDEMO较好地示范了BDE环境的配置,InterBASEServer高级功能应用,SQL服务器联接,触发器应用、存储过程编程和事务控制技术等,具有较高的参考价值。本节讲述下列内容:●数据库环境介绍●TDatabase的应用●不同数据库表的切换●触发器编程●存储过程编程●事务控制应用18.4.1数据库环境介绍本例中采用的数据库服务器是LocalInterBaseServer。LocalInterBase是InterBaseServer的单用户版32位、兼容ANSISQL。LocalInterBase支持客户/服务器应用在单机上的开发和测试,并且可以很容易地适化到InterBaseServer上。因此,开发客户/服务器应用采用LocalInterBase作为原型开发环境是很方便的。18.4.1.1IBLOCAL的BDE参数本例中的SQL数据库是IBLOCAL。它是由BDE配置工具(BDECFG32.EXE)设置参数值。它的各项参数值列于下表:表18.13IBLOCAL的各项参数值━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━参数名参数值────────────────────────────────────TYPEINTRBASEPATHSERVERNAMEC:\INTRBASE\EXAMPLES\EMPLOYEE.GDBUSERNAMESYSDBAOPENMODEREAD/WRITESCHEMACACHESIZE8LANGDRIVERSQLQRYMODESQLPASSTHRUMODESHAREDAUTOCOMMITSCHEMACHCHETIME-1MAXROWS-1BATCHCOUNT200ENABLESCHEMACACHEFALSESCHEMACACHEDIR━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━18.4.1.2数据库结构介绍IBLOCAL数据库的结构都是由InterBase服务器工具交互式SQL工具(ISQL)定义的。用ISQL定义数据库,首先要用CreateDatabase命令建立数据库,建立的新数据库一般是以GDB为扩展名。建立好后,就可以用SQL语言定义数据库表,例如建立EMPLOYEE表的SQL语句如下:定义域名数据类型:CREATEDOMAINFIRSTNAMEASVARCHAR(15);CREATEDOMAINLASTNAMEASVARCHAR(20);CREATEDOMAINCOUNTRYNAMEASVARCHAR(15);CREATEDOMAINEMPNOASSMALLINT;CREATEDOMAINDEPTNOASCHAR(3)CHECK(VALUE='000'OR(VALUE'0'ANDVALUE='999')ORVALUEISNULL);CREATEDOMAINJOBCODEASVARCHAR(5)CHECK(VALUE'99999');CREATEDOMAINJOBGRADEASSMALLINTCHECK(VALUEBETWEEN0AND6);CREATEDOMAINSALARYASNUMERIC(15,2)DEFAULT0CHECK(VALUE0);建立EMPLOYEE表:CREATETABLEEMPLOYEE(EMP_NOEMPNONOTNULL,FIRST_NAMEFIRSTNAMENOTNULL,LAST_NAMELASTNAMENOTNULL,PHONE_EXTVARCHAR(4),HIRE_DATEDATEDEFAULT'NOW'NOTNULL,DEPT_NODEPTNONOTNULL,JOB_CODEJOBCODENOTNULL,JOB_GRADEJOBGRADENOTNULL,JOB_COUNTRYCOUNTRYNAMENOTNULL,SALARYSALARYNOTNULL,FULL_NAMECOMPUTEDBY(last_name||','||first_name),PRIMARYKEY(EMP_NO));CHECK语句是给数据库字段取值范围加约束条件。PRIMARY_KEY语句是给表建立关键字索引。如法炮制,就可以定义IBLOCAL中的所有表。IBLOCAL中的表包括:EMPLOYEECUSTOMERDEPARTMENTEMPLOYEE_PROJECTPROJECTSALESSALARY_HISCORY各数据库表中的内容如下:表18.14EmployeeDemoDB中各数据库表的内容━━━━━━━━━━━━━━━━━━━━━━━━━━━数据库表名表中内容───────────────────────────EMPLOYEE雇员信息CUSTOMER客户信息DEPARTMENT部门信息EMPLOYEE_PROJECT雇员负责的工程PROJECT工程信息SALES销售信息SALARY_HISTORY雇员薪水调整的历史信息━━━━━━━━━━━━━━━━━━━━━━━━━━━每个数据库表中都定义了关键字段。关于数据库表中的字段名、类型、大小,这里不再赘述。18.4.2应用程序分析18.4.2.1TDatabase部件的使用CSDEMO程序中定义了一个数据库模块部件——TDmEmployee,它是继承于TDataModule。TDataModule是在Delphi2.0中才出现的专门放置数据访问部件(如TDatabase、TTable和TQuery等)的框架。其它涉及数据库访问的窗体,只要在uses语句中插入数据库模块所在的库单元,该窗体上的数据库部件就可引用相应的数据库访问部件。在TDmEmployee中定义了一个TDatabase类型的部件──EmployeeDatabase。EmployeeDatagase的主要属性及属性值如下:表18.15EmployeeDatabase部件主要属性的取值━━━━━━━━━━━━━━━━━━━━━━━属性属性值───────────────────────AliasNameIBLOCALDatabaseNameEmployeeDemoDBKeepConnectionTrueLoginPromptFalseTransIsolationtiReadCommittedParamsUSERNAME=SYSDBAPASSWORD=masterkeyConnectedTrue━━━━━━━━━━━━━━━━━━━━━━━AliasName属性所指定的IBLOCAL,必须已经在BDE中配置好,DatabaseName属性指定要使用的数据库名,该数据库名是由应用程序自己定义的,因此不反应到BDE中,该属性值被TTable、TQuery等DataSet部件引用,并且出现在DataSet部件的DatabaseName下拉式列表框中。本例中的“EmployeeDemoDB”,被EmployeeTable,SalesTable等所有DataSet部件引用。Connected为True表明,应用程序与数据库将保持联接。KeepConnection属性为True,表明多次打开和关闭EmployeeDemoDB数据库中的任意表,应用程序将始终与数据库保持联接,这省却了重复注册的开销。LoginPrompt属性为False,表明应用程序自动处理与数据库的联接注册,因此,Params属性中定义了注册的用户名和口令:USERNAME=SYSDBAPASSWORD=masterkeyTransIsolation属性为tiReadCommitted表明,如果存在多个同时事务,则某一事务只允许读由其它事务提交了的数据。程序中EmployeeDatabase的应用还与事务控制等有关。下文中会介绍这方面的内容。18.4.2.2不同数据库表的切换在许多数据库应用中都要在不同数据库表之间相互切换,以响应用户输入条件或系统状态的变化。这时,往往需要特别的处理,例如改变光标形状或隐藏数据改变等,尤其是在客户/服务器应用程序中。因为是用SQL语句访问远程数据库,有时还要在服务器端执行计算任务,所以客户端的数据变化会有一定的间隔,因此应该让用户明白发生了什么。下面是CSDEMO在数据库表切换时的处理办法:procedureTFrmViewDemo.ShowTable(ATable:string);beginScreen.Cursor:=crHourglass;{向用户提示当前操作状态}VaryingTable.DisableControls;{隐藏数据变化}VaryingTable.Active:=FALSE;{关闭原来的数据库表}VaryingTable.TableName:=ATable;{更新数据库表名}VaryingTable.Open;{打开数据库表}VaryingTable.EnableCon