1、 分布式多层数据库系统的应用目 录第一部分 引言1.1 任务或问题:1.2 实际背景:1.3 我的工作1.4 特色(创新)第二部分 毕业设计课题2.1 设计课题2.2 设计时间2.3 设计人员及任务2.4 指导老师2.5 设计内容第三部分 系统方案论证3.1 软件定义3.2 体系结构规划第四部分 毕业设计内容4.1 分布式多层数据库开发简介4.2 服务器端程序的建立4.3 客户端程序的建立4.4 客户端实现 SQL 查询4.5 动态连接应用程序服务器的实现4.6 图书管理功能的实现第五部分 毕业设计心得体会第六部分 附录8.1 代码部分参考资料摘要本次毕业设计任务是通过开发一个分布式多层数据库
2、图书管理系统,学习用 delphi 开发分布式多层数据库系统。采用 Delphi6.0 和 MS Server2000 等软件为开发工具;通过对计算机硬件和软件解决方案的论证;对应用领域进行调查分析;参考各种资料和进行数据库编程实践。在指导老师的帮助下,已经基本上成功地实现了设计任务书的要求。使得设计的数据库系统能够实现一般数据库的管理。我们研究了数据库的查询优化问题。第一部分 引 言1.1 任务或问题:开发一个分布式多层图书管理系统,可以实现动态的连接应用程序服务器,只要对配置文件进行配置,就可以像网上邻居一样选择所要连接的应用程序服务器。并提供借书还书,图书和期刊检索等查询功能。1.2 实
3、际背景:随着社会发展,人类的生产、生活越来越离不开信息。谁拥有了更多更有效的信息,谁就将在竞争中处于有利地位。信息产业正在成为一个国家的支柱。数据作为信息的载体,其管理工具数据库对于信息技术的重要性,正日益得到人们的重视。只有拥有了先进的数据库技术,才能有效地管理好浩如烟海的数据,并从中提取出对自己有用的信息来加以利用。90 年代,人们开发 MIS 系统大都采用客户机/服务器结构,客户机/服务器结构既是硬件结构又是软件结构。即数据放在服务器上,程序在客户机上。进行数据访问时,由客户机提出请求(一般是 SQL 语句),服务器执行并给出结果。客户机/服务器对于优化了网络,提高了系统的利用率。客户机
4、/服务器体系结构的发展经历了从二级体系结构模式到三级体系结构模式。1.3 我的工作设计系统框架,设计数据库,编写代码,测试数据等。1.4 特色(创新)可以像网上邻居一样选择所要连接的应用程序服务器。第二部分 毕业设计课题2.1 设计课题漳大图书馆管理系统2.2 设计时间二四年 10 月至二四年 12 月2.3 设计人员及任务王东凯 动态连接服务器模块的实现及帮助件功能模块的实现王开斌 分布式多层数据模块的实现王杰林 图书管理功能模块的实现陈庆辉 sqlserver 2000 数据库的分析及表的设计2.4 指导老师苏绿园 2.5 设计内容利用 Delphi6.0 和 MS Server2000
5、为主要开发工具,以 WindowsXP 为开发平台。设计出分布式多层应用的图书馆管理系统。可以实现动态的连接应用程序服务器,只要对配置文件进行配置,就可以像网上邻居一样选择所要连接的应用程序服务器。实现与应用程序服务器快速而准确的连接。第三部分 系统方案论证3.1 软件定义 数据库设计所要的解决的问题是:对于一个给定的应用领域,设计优化的数据库逻辑和物理结构,使之满足用户的信息管理要求和数据操作要求,有效地支持各种应用系统的开发和运行。数据库设计的目标是为用户和各种应用系统提供一个高效的运行环境。而数据库的设计可以视为如下的优化问题。(1) 计算机的软硬件环境;(2) 数据库管理系统的能力;(
6、3) 用户的操作要求与信息要求;(4) 完整性和安全性约束。3.2 体系结构规划本次设计的系统采用 三层客户/服务器体系,为了便于理解,我们先从二层客户/服务器体系结构来阐述:客户/服务器是在网络基础上,以数据库管理为后援,以计算机为网上工作站的一种系统结构。该结构的关键在把网络环境上的数据库存取和应用程序一分为二,分别由网上的数据库服务器和网上客户来执行。虽然本系统客户/服务器是建立在 LAN 的基础上,但它比以往的文件服务系统有了很大的改进。首先,它消除了不必要的网络传输负担;其次,它可以使作为数据库服务器的计算机被高度优化,以适应数据处理的需要。客户/服务器已经能够应用于复杂的网络上,并
7、使之能够更有效地进行选择、检索、索引排序等数据处理。作为一种高级的分布式计算机环境、客户/服务器有足够的能力把处理后的结果(不是整个文件)通过网络传输出去,并根据用户需求灵活地配置各种大、中、小型计算机系统。3.3 系统设计数据流图管理要求 查询要求管理结果 查询结果(顶层数据流图)图书管理系统管理人员 用户数据库设计过程数据库的设计过程如下图所示。在数据库设计过程中,需求分析和概念设计可以独立于任何数据库管理系统进行。逻辑设计和物理设计与具体的数据库管理系统密切相关。由于需求分析比较重要。我们在设计的时候,花了比较多的时间。在获得这些资料之后,进行分析。从中提取有用的部分。分析各种用户的权限
8、。需求分析说明书概念数据库模式独立于数据 (高级数据模型)库管理系统与数据库管理系统相关逻辑数据库模式(特定数据模型)物理数据库模式(特定的物理存储结构和存取方式)图:数据库设计过程第四部分 毕业设计内容现实世界需求分析概念数据库设计逻辑数据库设计物理数据库设计4.1 分布式多层数据库开发简介Delphi 提出的 MIDAS(Multi-Tier distributed Application Services Suite 多层分布式应用服务器组) ,是把原来 Two- Tier 数据连接放到了服务器端的 COM 组件上,客户端只剩下了执行文件和MIDAS.DLL,前台和服务器上的 COM 组
9、件,通过 DCOM 机制互相沟通。这个多的一层,称为应用程序服务器(Application Server) ,或者称为中间件。整个工作机制见下图:这种多层分布式工作机制,主要基于这样几点考虑:1) 减少客户机的维护量,因为前台程序比较简单;把企业逻辑封装在通用的中间件应用服务器中,不同的客户都可以共享同一个中间层(包括Web) ,而不必每个客户都单独实现企业规则,避免了重复开发和维护的麻烦。由于客户程序相当瘦(这就是现在流行的瘦客户机概念) ,无论是开发还是发布,都变得简单了。2) 便于升级,当中间件升级的时候,客户程序可能不需要变化;3) 实现了分布式数据处理,把一个应用程序分布在几台机器上
10、运行,可以提高应用程序的性能,也可以把敏感部分封装在中间件,为不同的用户设置不同的访问权限,增强了安全性。4) 减少直接连接数据库的用户数目,减少费用。在 Delphi 6.0 上,在原来的 MIDAS 基础上,发展了 DataSnap 技术,在很多细节方面,它提供了原来MIDAS 所没有的许多功能,使用上更加方便了。DataSnap 主要提供客户端和中间件之间的通信,不但支持 COM+技术也支持 TCP/IP 或者 CORBA,它们使用类似的界面和方法,其结果由程序自动完成,这就大大扩充了它的应用范围。必须要提醒的是,前台机器上除了应用程序以外,还必须把一个 MIDAS.DLL 文件复值到前
11、台机器上,这个文件在服务器的 WINNTSystem32 目录下。4.2 服务器端程序的建立服务器端程序实际上是个 COM 工程,它本身连接数据源,再通过接口与客户端联系,这个 COM 工程必须注册在服务器上。首先建立一个空白的工程,在工程里放置一个 Adoconnection 组件。然后再建一个远程数据模块file - New - Other - Multitier - Remote Data Module(远程数据模块)。 Coclass Name : libserver ,Instancing :执行模式,大部分用 Multiple Instance(多重实例),Threading Mo
12、del:线程模式,建议用 Apartment(单元),产生一个窗口,在这个窗口里,可以放入数据控件。在 Viwe - Type Libray 中,我们可以看到这个 COM 的一些特性。我们也可以记下系统提供的GUID,以备后来使用。加入一个 ADOTable,并设置其指向一个数据库。再设置一个 DataSetProvider(在DataAccess 页)指向 ADOTable,这就完成了服务器端的程序设计。保存,编译,注册(注意,只要运行就自动在本机注册了) 。4.3 客户端程序的建立 在 Two-Tier 模式中,客户端(Client)程序是直接和服务器的数据源相连的,而 Multi-Tie
13、r 模式,多个客户端连接的是一个应用程序服务器,因为收费是按客户端数计算的,所以,数据库的使用费用比较低。1)建立一个普通的工程。 2)放置一个 TDCOMConnrction 控件(在 Datasnap 页) ,属性:在本机注册时,可直接设置以下属性:ServerName:应用程序服务器注册名(server.libserver) ,Connected=true。这时你可以看到服务器端的 COM 程序被激活了。如果在网络上调试,需要给出服务器名:ComputerName:服务器名(自动给出网上邻居)注意: ServerGUID 的 GUID 值是自动给出的。3)放置一个 TClientData
14、Set 控件(在 Data Access 页) ,属性 RemoteServer= DCOMConnrction1,ProviderName:=DataSetProvider1(服务器端将被激活),Active=true (激活后将能正常连接)4)放置 TDataSource,属性:Dataset:指向 cdsCustomer。这样一个客户端程序就建立好了,其余犹如普通的数据库设计。44 客户端实现 SQL 查询由于在客户端不存在 TQuery 控件,似乎客户服务器模式是无法做 SQL 查询的。但是,Delphi 很好的解决了这个问题。事实上,只要客户端连接上服务端应用程序,客户端的 TCli
15、entDataSet 就包含了一个名字为 Provider 的属性,对应到服务器端 DataSetProvider 的所有默认属性和方法,其中DataSetProvider 有一个 Options 属性,只要让其中的 poAllowCommandText=true, 那么,DataSetProvider 的 poAllowCommandText 就可以接受前台来的 SQL 命令,并传送给 TQuery。可以看出,真正传递数据的是 DataSetProvider 的接口,所以,用这个接口搭建传递 SQL 的桥梁是必需的。客户端进行 SQL 查询的方法是:ClientDataSet.Close;C
16、lientDataSet.CommandText := SQL 语句;ClientDataSet.Open; 45 动态连接应用程序服务器的实现客户端程序在运行时,需要连接应用服务器程序以取得服务。但是,在系统实际应用的时候,运行应用服务器程序的计算机是经常改变的,因此在客户端程序启动时,应该先找到运行应用服务器程序的计算机的设置。动态连接应用服务器的流程类似于 12.3 节的动态数据库连接,动态连接应用服务器程序的流程图 14-1 所示。掌握了动态连接应用服务器的流程,就可以具体实现它。下面就将分步骤介绍动态连接应用服务器的实现过程。(1) 在 Delphi 中新建一个窗体,将单元文件保存为
17、 connect.pas 窗体的 Name 属性设为fm_serconfig,Caption 属性设为”服务器配置” ,运行后窗体如下图所示。(2) 在“连接设置”窗体中,需要输入应用服务器主机名(或者应用服务器 IP 地址)和应用服务器的端口号,这些配置信息将用来连接应用服务器。如果连接成功,输入的配置信息将被写入到注册表中,以后程序启动时,读取注册表配置信息,就可而已连接应用服务器程序了。程序的具体实现部分如程序清单如下所示。procedure BitBtn1Click(Sender: TObject);procedure Button1Click(Sender: TObject);pri
18、vateprocedure WriteToReg(const bappHost,bappIp,aPort:string); Private declarations public Public declarations end;varfm_SerConfig: Tfm_SerConfig; Connected: boolean= false; /代表是否连接成功implementationuses netlist, data;$R *.dfmprocedure Tfm_SerConfig.BitBtn1Click(Sender: TObject);beginif (Edt_host.Text=
19、) or (Edt_host.Text=null)and(Edt_ip.Text=) or (Edt_host.Text=null) thenbeginapplication.MessageBox(请输入服务器和 IP,输入错误,mb_iconinformation + mb_defbutton1);exit;end;trystrtoint(edt_Port.text);exceptApplication.MessageBox(请输入正确的端口号, 输入错误 ., mb_iconinformation + mb_defbutton1);exit;end;statusbar1.Panels0.T
20、ext:=正在连接服务器,pleale wait;statusbar1.Refresh;screen.Cursor:=crHourGlass;fm_data.Socket.Connected:=false;fm_data.Socket.Host:=edt_host.Text;fm_data.Socket.Address:=edt_ip.Text;fm_data.Socket.Port:=strtoint(edt_port.Text);tryscreen.Cursor:=crdefault;fm_data.Socket.Connected:=true;application.MessageBox
21、(连接成功,图书管理系统, mb_iconinformation + mb_defbutton1);connected:=true;exceptscreen.Cursor:=crdefault;application.MessageBox(连接失败,图书管理系统,mb_iconinformation+mb_defbutton1);connected:=false;end;/连接成功向注册表里写入应用服务器配置信息WriteToReg(edt_Host.Text, edt_IP.Text, edt_Port.Text);close;end;/利用可视化窗体来选择计算机procedure Tfm_
22、SerConfig.Button1Click(Sender: TObject);beginedt_ip.Clear;edt_host.Text:= NetExecute(TFm_NetList);end;/把信息写入注册表procedure Tfm_SerConfig.WriteToReg(const bappHost,bappIp,aPort:string);varreg:Tregistry;beginreg:=Tregistry.Create;reg.RootKey:=HKEY_LOCAL_MACHINE;if not reg.OpenKey(Softwarepz,false) then
23、/如果可以创建目录beginreg.CreateKey(Softwarepz);reg.OpenKey(Softwarepz,false);end;reg.WriteString(host,bapphost);reg.WriteString(ip,bappip);reg.WriteString(port,aport);reg.Free;end;end.打开“连接设置”配置窗口,在打开窗体之前,函数已经将布尔变量 Connected 设为 False,而在窗体被关闭之后,将返回 Connected 变量的值,根据布尔变量 Connected 的值可以判断是否已经连接上应用服务器。(3) 在连接设
24、置主窗口中,我们为应用服务器名提供了辅助录入的方法,点击应用服务器名编辑框右边的省略号按钮(Button1) ,将弹出一个浏览局域网计算机的对话框,以方便用户选择应用服务器所在的计算机。在此我们调用了一个 NetExecute 方法,它将返回用户选中的计算机的主机名。这个方法是如何实现的呢?下面将介绍 NetExecute 方法的实现过程。在 Delphi 中新建一个窗体,将窗体单元文件保存为 netlist .pas,窗体的 Name 属性设为Fm_netlist。运行后窗体如下图所示。在列举网络资源窗体中,将按照工作组以树型目录的形式显示局域网中的计算机。程序的具体实现部分如下所示。pro
25、cedure FormActivate(Sender: TObject);procedure TreeView1Click(Sender: TObject);procedure BitBtn1Click(Sender: TObject);privateprocedure getcomputername;procedure getgroupname; Private declarations public Public declarations end;function NetExecute(aFormClass: TFormClass): string;varfm_NetList: Tfm_N
26、etList;node: Ttreenode;aComputerName : string;/全局变量,存储选中的主机名implementation$R *.dfm/打开窗体,并返回选定的计算机function NetExecute(aFormClass: TFormClass): string;beginaComputerName := ;with aFormClass.Create(Application) dobegintryshowModal;finallyfree;end;result := aComputerName;end;end;procedure TFm_netlist.Fo
27、rmActivate(Sender: TObject);beginnode:=treeview1.items.add(Treeview1.topitem, 整个网络);node.imageindex:=0;treeview1.setfocus;end;procedure TFm_netlist.TreeView1Click(Sender: TObject);beginif treeview1.Selected.Level=0 thenbeginif treeview1.Selected.Count=0 then/添加工作组名getgroupname();end;if treeview1.Sel
28、ected.Level=1 thenbeginif treeview1.Selected.Count=0 then/添加计算机名getcomputername;end;if treeview1.Selected.Level=2 thenbitbtn1.Enabled:=trueelsebitbtn1.Enabled:=false;end;/取得计算机名procedure Tfm_netlist.getcomputername;varNetResource: TNetResource;Buf: Pointer;Count, BufSize, Res: DWord;Ind: Integer;lph
29、Enum: THandle;Temp: TNetResourceArray;groupname: string;my_node: Ttreenode;my_node_2: Ttreenode;beginscreen.Cursor := crHourGlass;statusbar.panels0.text := 正在列举组名.,请稍侯;statusbar.refresh;my_node := treeview1.Selected;groupname := treeview1.Selected.Text;FillChar(NetResource, SizeOf(NetResource), 0);
30、/初始化网络层次信息NetResource.lpRemoteName := GroupName1; /指定工作组名称NetResource.dwDisplayType := RESOURCEDISPLAYTYPE_SERVER; /类型为服务器(工作组)NetResource.dwUsage := RESOURCEUSAGE_CONTAINER;NetResource.dwScope := RESOURCETYPE_DISK; /列举文件资源信息/获取指定工作组的网络资源句柄Res := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,RE
31、SOURCEUSAGE_CONTAINER, NetResource, lphEnum);if Res NO_ERROR) then Exit; /执行失败Temp := TNetResourceArray(Buf);for Ind := 0 to Count - 1 do /列举工作组的计算机名称begin/获取工作组的计算机名称,+2 表示删除“,如wangfajun=wangfajunmy_node_2 := treeview1.Items.AddChild(my_node, Temp.lpRemoteName + 2);my_node_2.imageindex := 2;Inc(Tem
32、p);end;end;Res := WNetCloseEnum(lphEnum); /关闭一次列举if Res NO_ERROR then exit; /执行失败/获取整个网络中的网络类型信息Count := $FFFFFFFF; /不限资源数目BufSize := 8192; /缓冲区大小设置为 8KGetMem(Buf, BufSize); /申请内存,用于获取工作组信息Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);if (Res = ERROR_NO_MORE_ITEMS) /资源列举完毕or (Res NO
33、_ERROR then exit;for J := 0 to NetworkTypeList.Count - 1 do /列出各个网络类型中的所有工作组名称begin /列出一个网络类型中的所有工作组名称NetResource := TNetResource(NetworkTypeList.ItemsJ); /网络类型信息/获取某个网络类型的文件资源的句柄,NetResource 为网络类型信息,lphEnum 为返回名柄Res := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,RESOURCEUSAGE_CONTAINER, NetResource, lphEnum);if Res NO_ERROR then break; /执行失败while true do /列举一个网络类型的所有工作组的信息beginCount := $FFFFFFFF; /不限资源数目BufSize := 8192; /缓冲区大小设置为 8KGetMem(Buf, BufSize); /申请内存,用于获取工作组信息