Delphi三层数据库开发应用


======================================================
注:本文源代码点此下载
======================================================

这个主要是三层数据库开发学习用的。delphi学习者如果用的上这个mailto本人,空间放不下了,谅。

以下有关分布式数据库开发资料--来源网上

delphi 多层数据库开发

2006-10-20 04:22服务器端程序

http://hi.baidu.com/gzsunsos/blog/item/406918d5fe7be1c451da4bd6.html

服务器端程序实际上是个com 工程,它本身连接数据源,再通过接口与

客户端联系,这个com 工程必须注册在服务器上。

首先建立一个空白的工程。

file -> new -> other -> multitier -> remote data module(远程数据模块)

对话框:

coclass name : com程序的名称,前台依据这个名字查找com程序

(project121)

instancing:执行模式,大部分用multiple instance(多重实例)

threading model:线程模式,建议用apartment(单元)

下面我们就会对这几个选择详加说明。

ok,产生一个窗口,在这个窗口里,可以放入数据控件。

在viwe -> type libray 中,我们可以看到这个com 的一些特性。我们

也可以记下系统提供的guid,以备后来使用。

加入一个adotable,并设置其指向一个数据库。

再设置一个datasetprovider指向adotable

这就完成了服务器端的程序设计。

保存,编译,注册。

这里需要做几个说明:

1) 在客户端,数据控件一般要和datasource相连,但在服务器端,主

要要考虑数据和接口相连,delphi 5.0以上版本规定,使用datasetprovider

就不需要再针对每个控件做export(导出)操作,而是由应用程序服务器自

动帮前台查找这就简化了程序和维护量。但是,前台每个dataset 必须有个

对应的datasetprovider 才行。

2)关于建立com 是的几个选项现在说明一下:

a)instancing:

multiple instance: 一个应用程序可以被多个前台程序调用使

用,启动和执行的效率比较高,不耗费服务器太多的

资源,管理上也比较方便。

single instance: 一个应用程序只能被一个前台程序调用,由

于没有排队问题,所以当某个查询崩溃时,不会影响

其它的查询,但是,一个前台调用必然在服务器上建

立一个应用程序服务器的process (进程),占用资

源比较多,影响服务器整体执行效率。

internal: 建立一个in-process的com 程序(也就是dll文件

的格式),由于mult-tier 结构中,应用程序服务器

和前台程序是放在不同的地方的,两台机器的两个程

序就无法共享同一个process,所以很少设置成internal

模式的。

b) threading model:

apartment: 每个实例一次只能处理一个前台发出的request(请

求),如果同时建立多个in-process com 程序,那每

个com 程序就会有一个现程服务,所以数据是安全的,

当然要注意某些共享变量的冲突。

single:单线程,循环工作,不会出现多任务的问题。

free:可以让remote data module自己处理多线程问题,客

户端程序需要用多线程方法来处理。

both:和free几乎相同,但对应前台界面的callback都是连

续的。

如果注册后无法确认是否注册成功,可以用c:\winnt\regedit.exe检查。

在two-tier模式中,客户端(client)程序是直接和服务器的数据源相连的,

而multi-tier模式,多个客户端连接的是一个应用程序服务器,因为收费是按

客户端数计算的,所以,数据库的使用费用比较低。

下面的例子只提供了数据库操作的最基本的功能,主要说明数据源的连接

方法。

1)建立一个普通的工程。

2)放置一个tdcomconnrction控件(在datasnap页),属性:

computername:服务器名(自动给出网上邻居)

servername:应用程序服务器注册名(project121.test121server)

必要时serverguid输入guid值。

connected=true为激活

说明:在调试的时候,如果是在windows 2000本机的情况,可以先运行

project121.exe,然后就可以在servername中找到project121.test121server

了,然后connected=true激活。

3)放置一个tclientdataset控件(在data access页),属性:

name:cdscustomer(重新起名)

remoteserver: dcomconnrction1

providername: datasetprovider1(服务器端将被激活)

active:true (激活后将能正常连接)

4)放置tdatasource,属性:

dataset:指向cdscustomer。

其余犹如普通的数据库设计。注意到这里使用了tactionlist控件,其中

写入和退出在standard action 内找不到,需要自己编写:

procedure tform1.applyupdateexecute(sender: tobject);

begin

cdscustomer.applyupdates(-1);

showmessage('已经正确地写入数据库中!!');

end;

procedure tform1.closeactionexecute(sender: tobject);

begin

close;

end;

只要服务器端正确的注册,这个程序使用是没有问题的。

第四节客户端实现sql 查询

由于在客户端不存在tquery控件,似乎客户服务器模式是无法做sql

查询的。但是,delphi很好的解决了这个问题。事实上,只要客户端连接上

服务端应用程序,客户端的tclientdataset就包含了一个名字为provider

的属性,对应到服务器端datasetprovider的所有默认属性和方法,其中

datasetprovider有一个options属性,只要让其中的poallowcommandtext

=true, 那么,datasetprovider的poallowcommandtext就可以接受前台来

的sql 命令,并传送给tquery。

可以看出,真正传递数据的是datasetprovider的接口,所以,用这个

接口搭建传递sql 的桥梁是必需的。

客户端进行sql 查询的方法是:

clientdataset.close;

clientdataset.commandtext := 'sql语句';

clientdataset.open;

第五节客户端查询服务器端的别名集

在sql 查询以前,用户往往需要制定查询哪个数据库,所以需要把服

务器上bde 数据库别名(alias )设置数据抓到前台程序来

具体做法是:

首先,在服务器端建立一个tsession和一个tdatabase

session1属性:

sessionname=session1_4

database1属性:

databasename: 连接数据库名

sessionname:session1_4(sessionname值)

tqurey 增加个属性

sessionname:session1_4

这样就可以用session对象来管理数据源的信息了。

为了传给客户端值

view -> type library 显示接口窗口。

右键 itest125server(具体根据设置名不同而不同) -> new ->

建立两个方法:

getdatabasenames ,用以传下别名数据,其接口信息为:

return type :hresult

parameters

nametypemodifier

paramvariant*[out,retval]

setdatabasename , 用以接受客户机来的信息,其接口信息要求传入

三个信息。

return type :hresult

parameters

nametypemodifier

dbnamebstr[in]----传上来的别名

usernamebstr[in]

passwordbstr[in]

刷新(refreshimplementation)以后,就产生两个函数

function ttest125server.getdatabasenames: olevariant;

var

i: integer;

dbnames: tstrings;

begin

// 建立一个字符串数组存放bde所有的数据库别名数据。

dbnames := tstringlist.create;

try

// 利用session控件取得当前bde所有的数据库别名数据。

session1.getdatabasenames(dbnames);

/// 建立一个变量数组给函数返回变量result。

result := vararraycreate([0, dbnames.count - 1], varolestr);

// 最后再把数据库别名数据指定给该变量数组。

for i := 0 to dbnames.count - 1 do

result[i] := dbnames[i];

finally

dbnames.free;

end;

end;

上面的函数的关键除了取得bde 数据库别名以外,还声明了一个变量数

组来存放数据库别名数据,所以用vararraycreate函数建立一个变量数组,

其中参数1: 指定数组范围

参数2: 数组数据类型,由于别名要通过dcom传给前台,数据类型必

须设成varolestr 才有效。

第二个过程是客户机提供上来的联机数据。

procedure ttest125server.setdatabasename(const dbname, username,

password: widestring);

begin

try

// 把前台传来的数据库别名、用户上线名称、用户上线密码

// 等三项数据指定给tdatabase控件,并且执行联机的操作。

database1.close;

database1.aliasname := dbname;

if (username'') then begin

database1.params.values['password'] := password;

database1.params.values['user name'] := username;

end;

database1.open;

except

// 如果联机时发生错误,则产生一个exception给前台程序

// 前台程序将会利用到这个exception来判断是否要把输入上

// 线数据的窗口激活。

on e: edbengineerror do

raise exception.create('password required') ;

end;

end;

第六节服务器端进行客户计数

除了上面的功能外,这个程序还加上了一个在线用户以及查询用户统计

的功能。由于这个应用程序执行模式是 multiple instance执行模式,所以

当某个前台第一次连上线后,应用程序服务器会激活remotedatamodule的

事件程序,而断线后又会执行ondestroy事件程序,因此就可以用这两个事件

计算连上服务器的用户个数。至于query个数的计算,则由tquery的onafteropen

事件函数判断。

-----------------------------------------------------------------

form1部分,主要用于显示

-----------------------------------------------------------------

procedure tmainform.updateclientcount(incr: integer);

begin

fclientcount := fclientcount + incr;

clientcount.caption := inttostr(fclientcount);

end;

procedure tmainform.incquerycount;

begin

inc(fquerycount);

querycount.caption := inttostr(fquerycount);

end;

--------------------------------------------------------

com部分

--------------------------------------------------------

procedure ttest125server.remotedatamodulecreate(sender: tobject);

begin

// 增加一位前台上线者(调用form1上的程序)

mainform.updateclientcount(1);

end;

procedure ttest125server.remotedatamoduledestroy(sender: tobject);

begin

// 减少一位前台上线者(调用form1上的程序)

mainform.updateclientcount(-1);

end;

procedure ttest125server.adhocqueryafteropen(dataset: tdataset);

begin

// 新打开一个tquery查询(调用form1上的程序)

mainform.incquerycount;

end;

上述完整的客户/服务器数据库实例,见sql服务器和sql客户端两个程

序,数据源部分需要自己调整。

第七节一对多表的服务器端程序

一、application server

事先要有一个标准的form

file -> new -> multitier -> remote data module

coclass name :test63

instacting:multiple instacting

threading model: apartment

放入 adotable1

adotable2

datasouce1

datasetprovider1(在data access)

datasetprovider2

属性:

adotable1(主表)

adotable2(从表)

用connectionstring和tablename连上数据库

adotable1datasetprovider1

datasouce1

adotable2datasetprovider2

连上相应的数据库(这里为: 奖金数据库.mdb)

tadoquery.sql=select * from 奖金

tadoquery.active=true

tdatasetprovider.dataset=adoquery1

保存(工程名改为pchpserver),运行(注册)

客户端

dcomconnection1

属性:computername=计算机名(本地可以不写)

servername=服务器端程序名(com)

connecter=true (表示连上)

clientdataset1

属性:remoteserver=dcomconnection1

providername=datasetprovider1

active-=true

clientdataset2

属性:remoteserver=dcomconnection2

providername=datasetprovider2

active-=true

加入两个tdatasource,tdbgrid分别连上

clientdataset1和

clientdataset2

似乎应该显示主从关系了,但dbgrid2并没有显示。

解决办法:

双击clientdataset1,出现form1.clientdataset1窗口,右键,快

捷菜单上选add field 这时,我们可以看到最后一行出现:adotable2

这是很重要的,正是靠这个建立了主从联接关系

ok让它进入form1.clientdataset1窗口(也可以调整主表所显示

的字段,但adotable2 不能少,它实际上是把从表作为主表的一个字段

使用了)。

clientdataset2属性:

datasetfield=clientdataset1adotable2

active=true

主从关系建立起来了。

=========================

长青树,专注web技术,关注前端开发

web开发技术交流qq群:4063275

承接中小企业软件开发

┃承接┃软件开发|网站建设|电子商城|

┃出售┃采集软件|考勤系统|域名空间|

绿色通道:好文要顶关注我收藏该文与我联系


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值