面向连锁超市管理系统的分布式数据库设计与实现_第1页
面向连锁超市管理系统的分布式数据库设计与实现_第2页
面向连锁超市管理系统的分布式数据库设计与实现_第3页
面向连锁超市管理系统的分布式数据库设计与实现_第4页
面向连锁超市管理系统的分布式数据库设计与实现_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/分布式数据库课程设计和实现——面对连锁超市管理系统的分布式数据库设计和实现学院:计算机学院专业:计算机科学和技术专业组长:张王成2120111220组员:耿丙辉2120111140闫高洁2120111212李杰2120111157石玉龙2120111246日期:2011年11月27日书目1. 连锁超市管理系统概述 11.1 背景介绍 11.2可行性分析 11.3系统目标和先进之处 21.4小组成员和任务支配 32. 需求分析 42.1用户需求概述 42.2业务需求分析 52.3功能分析 63. 系统总体设计 83.1绘制用例图设计系统功能 83.2绘制系统流程图 93.3系统开发环境 103.4系统的运行环境 113.5系统运行演示 113.6系统类库设计 144. 分布式数据库分析和设计 164.1数据库分析 164.2数据库概念设计 164.3数据库逻辑结构设计 204.4分片和位置支配设计 24站点通信模型 24数据表的分片和位置支配设计 255. 基于SQL的SMS的详细设计(实现) 275.1公共类设计 27文件操作类CFileOperate 27时间格式转换类CMyTime 29数据操作类CADOConn 29数据库表的操作类CtablePartInfo 375.2界面窗口设计 41系统启动登录开发 41主界面对话框设计 43通用报表对话框设计开发 44打印对话框设计开发 465.3基本资料模块设计 485.3.1基本资料管理功能开发 485.3.2价格自动生成功能开发 525.3.3报表功能实现 545.4进货/销售模块设计 55进货/销售登记设计 55进货设计 59月度统计设计 615.5库存模块设计 625.5.1库存查询功能开发 625.5.2库存报警功能开发 636. 开发技巧和难点分析 646.1OLE技术运用 646.2MFCGridControl控件的运用 65连锁超市管理系统概述背景介绍随着市场经济的发展和人民生活水平的提高,原来单一、小规模的超市已无法满足人民对购物环境的要求,大规模、物品丰富的超市正在蓬勃发展。超市销售数据规模的日益浩大,商品数目的快速增长,接受以往的手工管理已干脆或间接地降低了工作效率,最终影响超市的日常运转。另外超市的发张壮大,尤其是连锁超市(如家乐福、美廉美)的扩张,使得他们具有地域上分散而管理上又相对集中的特点,往往既要有各门店的局部限制和分散管理,同时也要有整个组织的全局限制和高层次的协同管理。因此把这些门店和中心通过网络连接起来,设计开发一款基于分布式数据库的连锁超市管理系统SMS(Supermarketmanagementsystem)势在必行。1.2可行性分析(1)经济可行性运用连锁超市管理系统对超市连锁店进行信息化管理将干脆提高公司管理部门的工作效率。通过网络远程提交汇总各门店的信息,节约了许多的时间和金钱。另一方面,用信息化管理统计大量数据,节约了许多的人力和财力,为管理者供应更好的决策支持。(2)技术可行性网络应用基础设施完善,由于信息技术的发展,我国的计算机网络飞速发展,先后建成了中国公众多媒体通信网、ChinaNet、中国教化和科研计算机网络等组成了中国Internet主体,网络应用进入企业和一般家庭,这为发展连锁超市网络办公供应了基础设施。网络平安技术应用,包括加密算法、CA数字认证、数字签名等,为网络办公系统的应用供应平安保证,它实现了网络传输数据的平安性、完整性等。最终,就是网络技术的普及和驾驭,如网络互联、网络平安技术、网络数据库技术等,使我们有实力开发实现适合自己的管理系统。因此,公司构建跨区域的管理系统的技术瓶颈问题(网络应用基础设施、网络平安、开发技术)得到了有效解决,公司构建网络管理系统技术上可行。(3)操作可行性由于SMS的操作是基于C/S的客户端的页面操作,简洁明白,用户无需学习,一般都能够很简洁的知道如何操作。而管理员也无需具备专业学问,只须要对一些数据进行输入以及平常的日常维护就够了。1.3系统目标和先进之处(1)系统目标为连锁超市提高效率、降低成本;实现连锁超市管理的优化,简化工作流程,节约人力物力,提高工作效率,极大地满足客户须要;对各环节进行限制分析,实现统一调度。满足连锁超市的基本管理功能,发挥信息系统的灵敏性,减轻企业管理人员和操作人员的工作负担,提高工作效率。本系统是一项功能比较完善的连锁超市管理系统,对连锁店运作过程中的后台数据可以随时进行分析,便于企业管理人员的经营、决策。全面体现了现代企业管理理论所提倡的工作高效、环境轻松的氛围。(2)系统先进之处多数处理就地完成。各地的计算机由数据通信网络相联系。克服了中心数据库的弱点:降低了数据传输代价。提高了系统的牢靠性,局部系统发生故障,其他部分还可接着工作。各个数据库的位置是透亮的,便利系统的扩充。为了协调整个系统的事务活动,事务管理的性能花费高。1.4小组成员和任务支配任务支配成员姓名任务支配、组织调度调查、明确连锁超市的需求和业务流程系统总体设计系统的编码实现设计文档的最终排版、批阅张王成建立实体-关系模型,E-R图的绘制UML建模中的用例的分析设计、用例图的绘制数据库支配和分片的概要设计,相关图例的绘制设系统联合测试石玉龙调查、明确连锁超市的需求和业务流程基于SQLserver和Access的分布式数据库实现系统的编码实现耿丙辉基于SQLserver和Access的分布式数据库实现系统的编码实现汇报PPT制作,项目最终成果汇报闫高洁核心数据库表的设计系统通信模型的建立,相关图例的绘制数据库支配和分片的概要设计,相关图例的绘制系统联合测试李杰需求分析2.1用户需求概述下面是通过调查探讨获得的关于连锁超市主要信息数据的需求分析结果:(1)连锁超市通常由一个中心(公司总部)、多个远程连锁店(门店)组成,并且每个连锁店分布在不同地域。(2)连锁超市的各个部门之间、各个分店之间、分店和总部之间须要交换数据,这种数据交换是通过局域网和广域网进行的。(3)公司总部负责产生并管理该连锁超市的整体汇总数据,即各门店的明细汇总表数据,如销售汇总表等。(4)每一个远程站点(各门店和公司总部)分别有一个数据库系统,各自组成一个独立的子系统,可以分别独立进行本部门业务处理。(5)总部为了便于对各店进行管理,同时也为了比较各店的销售状况,要求门店将全部商品归入相应的商品类别,由总部统一管理并供应各门店运用,而且,商品类别信息数据在各门店都要经常运用。(6)有关商品信息、供应商信息、POS机信息、进货信息和销售信息等经营基础数据都是各门店单独管理和运用,门店之间互不相关。(7)整个连锁超市的职员信息由公司总部管理和维护,各门店只可以查询本部门的职员信息。2.2业务需求分析通过对超市的营业、管理业务流程的调查,得到下面的业务需求。可以对商品类别、商品、供应商、POS机等基础信息进行管理。可以实现选购 开单、销售开单、选购 退货、销售退货等基本功能。软件可依据商品资料中设置的最高库存、最低库存进行库存报警。商品的批发价、零售价可自动生成,减轻定价的工作量。可以生成各类统计报表,供应详尽的营业报告,实现对商品进、销、存及利润等财务状况了如指掌。全部单据、报表均可以在打印前预览,并且可以导出为Excel文件,然后依据实际须要进行特别的编排处理。为了系统平安,每次用户登录都创建相应的日志文件,记录用户的全部操作。此外,对系统的性能主要有以下几个方面的需求。系统在设计过程中应充分考虑到可扩充性,要求操作界面美观大方,简洁上手。2.3功能分析依据对系统的业务调查和用户的需求分析,结合计算机信息管理的特点,设计系统实现的功能如下。基础信息管理基础信息管理包括业种商品类别信息、商品信息、供应商信息、POS机信息和价格信息维护和管理,实现的功能包括:基本信息的添加、删除和更新操作。生成各类基础信息报表。打印和导出报表。进货管理进货管理主要实现对商品的选购 入库信息进行管理,详细实现功能如下:进货开单,实现商品的进货结算、入库操作。进货退货,退还商家相关的商品。生成进货、退货的单据、商品报表。打印和导出报表。销售管理销售管理主要实现对商品的销售出库相关信息进行管理,详细实现的功能如下:销售开单,实现商品的销售结算、出库操作。销售退货,允许客户退出相关的商品。生成销售、销售退货的单据、商品报表。打印和导出报表。库存管理库存管理主要实现对商品的库存相关信息进行管理,详细实现的功能如下:库存查询,可以查看全部库存商品的相关信息。库存报警,对库存过多或过少的商品进行报表统计。库存盘点,可以修改商品的库存数量。帐务管理帐务管理主要实现对营业员的销售商品、业务提成、营业收入等状况进行分类报表统计。数据管理数据管理主要实现对数据库数据进行备份、还原及清理等相关工作。系统管理系统管理主要实现登录用户(职员)管理、系统日志、修改登录密码等相关工作。系统总体设计3.1绘制用例图设计系统功能用例图表示了角色和用例以及它们之间的关系。它描述了系统、子系统和类的一样的功能集合,表现为系统和一个或多个外部交互者(角色)的消息交互动作序列。也就是角色(用户或外部系统)和系统(要设计的系统)为了实现一个目的交互,这个目的的描述通常是一个谓词短语,例如签合同等。系统设计包含超级管理员、管理员和营业员四种用户角色。超级管理员具有全部的操作权限,其用例图如图3-1所示。图3-1超级管理员角色系统用例图管理员不具备系统设置模块中的用户管理和商品类别信息管理功能,其他功能均具备。而销售人员则只具有销售开单管理功能。3.2绘制系统流程图结合系统的详细设计要求,连锁超市管理系统的主要功能流程图如图3-2所示。图3-2系统主要功能流程图系统首先对登录用户身份进行验证,依据用户的权限激活相关功能。超级管理员具有全部的操作权限,系统的功能结构图如图3-3所示。图3-3系统功能结构图上图只是列出了一些主要功能,系统还能够依据不同需求生成各种统计报表。3.3系统开发环境本系统是在WindowsXP中文版操作系统环境下,运用MicrosoftVisualStudio2008中文版用C++语言开发成功的。在开发过程中,运用了OLE技术和ActiveX控件技术。后台数据库系统设计接受的是Microsoft的SQLServer2005和Access数据库系统,通过ADO数据库开发技术,干脆操作数据库文件。3.4系统的运行环境系统可以干脆在Win98、Win2000、WinXP环境下运行。系统预设的超级管理员用户名为“admin”,密码为“admin”。3.5系统运行演示程序启动,首先弹出如图3-4所示的“系统登录”对话框,只有输入正确的用户ID、登录密码才能进入系统能够。图3-4“系统登录”对话框假如登录用户为超级管理员或管理员,会进入系统的主界面窗口,如图3-5所示。图3-5系统的主界面窗口假如登录用户权限为营业员,由于其只具有售货权限,因此系统会干脆弹出“销售开单”对话框,如图3-6所示。图3-6“销售开单”对话框在进行相关操作前,首先须要添加、设置一些基本资料,如商品分类登记,其操作设置对话框,如图3-7所示。图3-7“商品分类登记”对话框另外,系统还供应了丰富的报表功能,如图3-8所示的商品分类报表,同时对报表供应了导出到Excel文件和打印的功能。图3-8商品分类报表对话框3.6系统类库设计BITVRLab超市管理系统主框架的设计是通过MFC创建向导创建的基于对话框的窗口程序,在对话框程序中添加了菜单栏,系统的主要类库设计如下。自定义扩展类:为了提高开发效率、便于代码重用,自定义了一些数据操作类和控件扩展类,如表3-1所示。表3-1自定义扩展类及功能类说明CADOConn通过ADO实现对ACCESS、SqlServer等数据库的访问CtablePartInfo依据数据库表的支配、分片信息,实现对数据库表的增、删、改、查CFileOperate实现对硬盘文件的常用操作CMyChiToLetter实现依据逐字提取汉字拼音的首字母CMyButtonCButton类的派生类,实现带有位图和文本的按钮CMyMenuCMenu类的派生类,用于定制自己的菜单CMenuItemContextCMenu类中用到此类,用于保存菜单项的信息CMyTime实现简洁的时间格式的转换CMyExcel完成VC对Excel文件的操作对话框窗口类:在系统中,用户全部的数据查询、操作都是通过对话框窗口来实现的,系统开发的对话框类如表3-2所示。表3-2对话框类及说明类说明CDlgFenJiBasePOS机基本信息管理对话框类CShopManageDlg主框架对话框类CDlgFenLeiBase商品分类基本信息管理对话框类CDlgDanganBase商品基本信息管理对话框类CDlgGongYingShangBase供应商基本信息管理对话框GDlgJiaGeSheZhi价格自动设置对话框类CDlgJinHuoKanDan商品进货开单管理对话框类CDlgJinHuoTuiDan商品进货退单管理对话框类CDlgXiaoShouKanDan商品销售开单管理对话框类CDlgXiaoShouTuiDan商品销售退单管理对话框类CDlgAll用于查找信息显示对话框类CDlgReport用于报表显示对话框类CDlgLogo用户登录对话框类CDlgPwd更改密码对话框类CDlgQuit退出系统提示对话框类打印相关类:系统能够供应了报表的打印和打印预览功能,其相关的设计类如表3-3所示。表3-3打印相关类及说明类说明CPrintFrameCFrameWnd派生类,用于构建打印框架类CPrintView打印视图类另外,系统还包含一些主框架相关类、导入ActiveX控件(MFCGridControl)相关类和导入OLE对象(Excel)相关类。分布式数据库分析和设计4.1数据库分析考虑到总站点的信息量大接受SQLServer2005数据库,而区域站点信息量相对较小接受Access数据库。当区域业务拓展,操作终端增加时,Access数据库也很简洁的移植到SQLServer数据库系统中。另外区域站点接受Access数据库可以实现便利的部署。4.2数据库概念设计分析超市管理功能流程,系统的数据实体主要包括基本资料对象实体、库存实体、进货/销售开单、进货/销售退单、进货/销售商品实体、各站点数据库服务器IP信息实体、数据库表支配分片信息实体等。基本资料对象实体包括商品类别、商品明细、供应商、POS机和登录用户实体。商品库存实体记录库存商品的数量和价格信息,其实体的E-R图如下。商品进货单实体用于记录进货单的统计信息,其实体的E-R图如下所示。进货商品实体用于记录进货单对应的商品信息,其实体的E-R图如下所示。进货退单实体用于记录进货退单信息,其实体的E-R图如下所示。和进货相对应的销售单实体、销售商品实体和销售退单实体的E-R图如下所示。各站点数据库服务器IP信息,记录各个区域数据库服务器对应的IP地址,其实体的E-R图,如下图所示。数据库表支配分片信息,记录数据中全部的表的分布式支配和分片信息,其实体E-R图,如图所示。4.3数据库逻辑结构设计商品类别表、商品明细表、供应商表、POS机表、登录用户表、库存表、进货/销售开单表、进货/销售商品表、进货/销售退货商品表、IP地址登录信息表、数据库表的支配和分片信息。商品类别表:商品明细表:供应商表:POS机表:用户表:库存表:进货单表:进货商品表:进货商品退单表:销售单表:销售商品表:销售商品退单表:服务器IP信息表:分片及分布信息表:4.4分片和位置支配设计站点通信模型在我们的连锁超市管理系统中,有一个总店并下分多个分店,总店和分店之间或分店和分店之间都可以进行通信。每个分店是一个相对独立的数据库服务系统,其可以连接随意数量的客户端。通信模型如下图所示:4.4.2数据表的分片和位置支配设计依据以上得到的关于主要信息数据的需求分析结果,为该连锁超市系统的分布式数据库系统进行主要信息数据的分片和支配设计如下:1、数据的分片设计(1)由于该连锁超市系统的各连锁店之间在经营上是独立的,每个门店只关切自己的经营状况,有关供应商信息、POS机信息、商品信息和进货/销货信息等基础数据都是各门店单独管理和运用,门店之间互不相关。因此,商品明细表、供应商表、POS机表、库存表、进货/销售开单表、进货/销售商品表、进货/销售退货商品表依据地域(门店所在区域标记)接受水平分片的方法得到水平片段。(2)这里我们对于商品信息进行了垂直分片,分成了商品明细表和库存表,因为商品的某些属性,例如库存量等须要经常更新,因此将这些属性划分出来构成单独的实体可以削减系统开销。(3)由于整个连锁超市的职员信息由总公司管理和维护,各门店只可以查询本店的职员信息。所以职员信息不必分片,可以接受视图的形式供应应各门店查询本门店的职员信息。另外,各个区域数据库服务器的IP地址信息也只是由总部管理、维护,所以也不必分片。(4)由于商品分类数据由总部统一管理并供应各门店运用,而且,商品类别信息数据在各门店都要经常运用。因此,商品类别信息数据也不必分片。(5)该分布式数据库系统实现了简洁的书目管理,记录数据库中各个表的分片和支配信息,以便数据更新时,维护各个站点上数据的一样性。这个表由总部规划建立,各门店也会经常运用。因此,数据库书目信息表也不必分片。2、数据及其片段的支配设计(1)对于只在各门店单独运用的除商品类别信息和数据库书目信息以外的其他基础信息的片段,接受按区域分片然后支配到各个门店的数据库服务器上。总站上有全部门店的全部信息。(2)整个系统的职员信息、IP地址信息由公司总部管理和维护,所以只支配在总部站点中。(3)商品类别信息、数据库书目信息是由总部统一规定并下发到各门店的,由于各店经常会运用到这类基础信息,因此在各门店都具有相同的副本。所以,商品类别信息、数据库书目信息都不会分片但被复制,且复制的个数为门店的个数。基于SQL的SMS的详细设计(实现)5.1公共类设计为了提高程序代码的开发效率,便于代码重用,在系统开发中,创建了一些数据操作类和控件扩展类。5.1.1文件操作类CFileOperate为了便于对硬盘文件的操作,开发了文件操作类CFileOperate,它通过调用API函数实现常用的文件操作。CFileOperate类的声明代码如下。externCStringstrTmpPath;classCFileOperate{public: //构造函数 CFileOperate(); //取得当前程序运行的路径 CStringGetAppPath(); //推断是否存在strFn文件夹 BOOLIsFileExist(CStringstrFn,BOOLbDir); //制作strFloderName文件夹返回文件夹名 CStringMakeDirectory(CStringstrFloderName); //自动生成文件夹 CStringMakeDirectory(); //得到文件夹名为strFloderName的路径 CStringGetDirectoryPath(CStringstrFloderName); //删除strFloderdName文件夹 voiddelDirectory(CStringstrFloderdName); //删除主文件夹(data) voiddelMainDirectory(); //制作主文件夹 voidMakeMainDirectory(); //推断strIntDigit是否为整数,是否小于intBig BOOLCheckIntDigit(CStringstrIntDigit,intintBig); //推断strFileName是否可以做文件夹或文件的名字 BOOLCheckFileName(CStringstrFileName); //推断strText是否为空 BOOLCheckEmpty(CStringstrText); //删除strFloderName文件夹下名为strFileName的文件 voiddelFile(CStringstrFloderName,CStringstrFileName); //得到strFloderName文件夹下名为strFileName的文件路径 CStringGetFileName(CStringstrFolderName,CStringstrFileName); //制作strFloderName文件夹下名为strFileName的文件 CStringMakeFile(CStringstrFloderName,BOOLblnMake); //显示文件夹对话框 BOOLGetFolder(CString*strSelectedFolder,constchar*lpszTitle,constHWNDhwndOwner,constchar*strRootFolder,constchar*strStartFolder);系统程序中主要用到了CFileOperate类中的GetAppPath函数。GetAppPath函数用于获得当前运行程序所在文件夹的路径,其实现代码如下。CStringCFileOperate::GetAppPath()//取得当前运行程序所在文件夹路径{ charlpFileName[MAX_PATH];//路径数组 //获得当前运行程序的全路径 GetModuleFileName(AfxGetInstanceHandle(),lpFileName,MAX_PATH); CStringstrFileName=lpFileName; //从字符串的最右边向左搜寻'\\'串 intnIndex=strFileName.ReverseFind('\\'); CStringstrPath; if(nIndex>0) strPath=strFileName.Left(nIndex);//取'\\'串左边字符 else strPath=""; returnstrPath;//返回前运行程序的文件夹路径}5.1.2时间格式转换类CMyTime系统开发中,须要常见的对日期、时间数据进行操作,因此这里设计了类CMyTime,实现简洁的时间日期转换,CMyTime类的声明如下。classCMyTime{public: CTimeValueTime;//CTime类型的值 //blnChinese:TRUE-"年月日时分秒"FALSE-"-:" CStringGetAllString(BOOLblnChinese); //返回字符串形式的日期时间 //blnChinese:TRUE-"年月日"FALSE-"-" CStringGetDateString(BOOLblnChinese);//返回字符串形式的日期 //blnChinese:TRUE-"时分秒"FALSE-":" CStringGetTimeString(BOOLblnChinese);//返回字符串形式的时间 CStringGetSimpleString();//返回简洁字符串形式的日期时间 CStringGetWeek();//返回星期"星期日" //设置字符串形式的值 //blnSimple:TRUE-(%Y%m%d%H%M%S)FALSE-(年月日时分秒或-:) voidSetAllString(CStringValue,BOOLblnSimple); voidSetNow();//设置成现在时间 CMyTime();//构造函数};SetNow函数获得当前日期,时间,将其值赐予ValueTime。voidCMyTime::SetNow(){ ValueTime=CTime::GetCurrentTime();}5.1.3数据操作类CADOConn系统开发了数据操作类CADOConn,它是本系统的核心,实现了对数据库数据的基本操作功能,CADOConn类的声明代码如下。#import"c:\programfiles\commonfiles\system\ado\msado15.dll"\ no_namespacerename("EOF","adoEOF")classCADOConn{//定义变量public: _ConnectionPtrm_pConnection;//指向Connection对象指针: //添加一个指向Recordset对象的指针: _RecordsetPtrm_pRecordset; _bstr_tm_strData; intm_DataType; CADOConn(intDataType);//构造函数 CADOConn(); virtual~CADOConn(); voidOnInitCADOConn();//初始化连接数据库 _RecordsetPtr&GetRecordSet(CStringstrSQL);//执行查询 BOOLExecuteSQL(CStringstrSQL);//执行SQL语句,InsertUpdatedelete voidExitConnect();//退出连接 BOOLMoveFirst();//字段集移向开头 BOOLMoveNext();//字段集向下移 BOOLOpen(CStringstrSQL);//打开记录集 BOOLOpenLogo(CStringstrSQL);//打开记录集 CStringGetValueString(intindex,intstrSum);//返回记录集中某字段的字符串 byteGetValueByte(intindex);//返回记录集中某字段的字节 intGetValueInt(intindex);//返回记录集中某字段的短整数 doubleGetValueDouble(intindex);//返回记录集中某字段的双精度数 floatGetValueFloat(intindex);//返回记录集中某字段的单精度数 longGetValueLong(intindex);//返回记录集中某字段的长整型数 CTimeGetValueDate(intindex);//返回记录集中某字段的日期时间 //获得记录集某字段的BYTE值,并换为CString返回 CStringGetValueByteStr(intindex,intstrSum); //获得记录集某字段的INT值,并换为CString返回 CStringGetValueIntStr(intindex,intstrSum); //获得记录集某字段的Double值,并换为CString返回 CStringGetValueDoubleStr(intindex,intstrLSum,intstrRSum); //获得记录集某字段的Float值,并换为CString返回 CStringGetValueFloatStr(intindex,intstrLSum,intstrRSum); //获得记录集某字段的Long值,并换为CString返回 CStringGetValueLongStr(intindex,intstrSum); //获得记录集某字段的CTime值,并换为CString返回 CStringGetValueDateStr(intindex,CStringstrType); //添加单项数据 BOOLAddItem(CStringstrTable,intstrSum,LPCTSTRpszText,...); //得到字段中数据的类型 intGetValueType(intindex); BOOLadoEOF();//记录集的结束推断 BOOLFillList(CListCtrl*listMain,intColOpenEnd);//填充列表(ColOpenEnd代表绽开多少列) BOOLInitList(CListCtrl*listMain,intcolSum);//初始化列表 CStringGetAppPath();//得到应用程序所在的文件夹 BOOLFillList(CListCtrl*listMain);//填充列表 CStringGetFieldsName(intindex);//返回字段名字 intGetFeildsCount();//返回字段数量 //返回数据集数 longGetRecordCount(); voidWriteLog(CStringstrSql);//写日志文件 voidWriteLog1(CStringuserName);//写日志文件,谁谁登录};1、数据库操作函数对常用的数据库操作定义了相关函数。(1)连接数据库在类的构造函数CADOConn中,声明数据库的名称。CADOConn::CADOConn(){ m_DataType=1;//数据库类型Acess m_strData=_bstr_t("ShopData.mdb");//数据库名称}在OnInitCADOConn函数中,实现连接数据库。voidCADOConn::OnInitCADOConn(){ //初始化OLE/COM库环境 ::CoInitialize(NULL); try { //初始化指针 m_pConnection=NULL; //初始化指针 m_pRecordset=NULL; //创建Connection对象 m_pConnection.CreateInstance("ADODB.Connection"); //设置连接字符串,必需是BSTR型或者_bstr_t类型 _bstr_tstrConnect; switch(m_DataType) { case1://ACCESS strConnect=_bstr_t("Provider=Microsoft.Jet.OLEDB.4.0;"); strConnect=strConnect+_bstr_t("DataSource="); strConnect=strConnect+_bstr_t(IPAddress)+_bstr_t("\\data\\"); strConnect=strConnect+m_strData; break; case2://EXCEL strConnect=_bstr_t("Provider=Microsoft.Jet.OLEDB.4.0;"); strConnect=strConnect+_bstr_t("DataSource="); strConnect=strConnect+_bstr_t(GetAppPath())+_bstr_t("\\"); strConnect=strConnect+m_strData; strConnect=strConnect+";ExtendedProperties=Excel8.0"; break; case3://SQLSERVER strConnect="Provider=SQLOLEDB;Server="+MainIP+";Database=ShopData;uid=admin;pwd=123456"; break; } m_pConnection->Open(strConnect,"","",adModeUnknown); } //捕获异样 catch(_com_errore) { //显示错误信息 AfxMessageBox(e.Description()); } ASSERT(m_pConnection!=NULL);}(2)对数据库进行查询GetRecordSet函数实现执行Select查询语句,返回查询结果集_RecordsetPtr&CADOConn::GetRecordSet(CStringstrSQL){ try { //连接数据库,假如Connection对象为空,则重新连接数据库 if(m_pConnection==NULL)OnInitCADOConn(); strSQL.TrimLeft(); strSQL.TrimRight(); //创建记录集对象 m_pRecordset.CreateInstance(__uuidof(Recordset)); //取得表中的记录 m_pRecordset->Open(_bstr_t(strSQL),m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText); } //捕获异样 catch(_com_errore) { //显示错误信息 AfxMessageBox(e.Description()); } ASSERT(m_pRecordset!=NULL); //返回记录集 returnm_pRecordset;}CADOConn类的Open函数的实现和GetRecordSet函数基本类似,只是它不返回记录集,而是打开数据库表。(3)执行数据库操作语句ExecuteSQL函数实现执行SQL数据操作语句,如INSERT/UPDATE/DELETE语句等。BOOLCADOConn::ExecuteSQL(CStringstrSQL){ try { //是否已经连接数据库 if(m_pConnection==NULL)OnInitCADOConn(); strSQL.TrimLeft(); strSQL.TrimRight(); m_pConnection->Execute(_bstr_t(strSQL),NULL,adCmdText); WriteLog(strSQL); returnTRUE; } catch(_com_errore) { AfxMessageBox(e.Description()); returnFALSE; }}2、记录集操作函数为了便于对记录集进行操作,在CADOConn类中定义了常用的记录集操作函数。GetValueInt实现了从记录集中获得不同类型的字段值函数,以获得整形字段值。intCADOConn::GetValueInt(intindex){ _variant_tvValue;//var型返回值 _variant_tvIndex;//索引 intiValue;//数值返回值 vIndex.vt=VT_I2; vIndex.iVal=index; vValue=m_pRecordset->Fields->GetItem(vIndex)->Value;//获得索引字段的值 switch(vValue.vt) { caseVT_NULL://为空值 iValue=0;//赋值 break; caseVT_ERROR://错误 iValue=0;//赋值 break; caseVT_EMPTY://不存在 iValue=0;//赋值 break; default: iValue=vValue.iVal;//获得值 } returniValue;//返回整数值}3、列表控件操作函数在CADOConn类中定义了列表控件的操作函数,实现将记录集数据添加到指定的列表控件中。其中InitList函数实现初始化列表控件。BOOLCADOConn::InitList(CListCtrl*listMain,intcolSum){ longlMax=0; _variant_tvIndex;//var类型索引 vIndex.vt=VT_I2; inti; lMax=m_pRecordset->Fields->Count;//获得记录集字段数 //设置列表框控件风格 listMain->SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT); for(i=0;i<lMax;i++)//遍历各字段 { CStringstrTitle=""; vIndex.iVal=i;//字段索引 //获得字段名称 strTitle=(LPCTSTR)m_pRecordset->Fields->GetItem(vIndex)->GetName(); //在列表框中添加列 listMain->InsertColumn(i,strTitle,LVCFMT_CENTER,100,0); } intintWidth=0;//列表框列的宽度 for(i=0;i<colSum;i++)//遍历列表框中添加列 { //依据字段标题自动设置列宽 listMain->SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER); intWidth=intWidth+listMain->GetColumnWidth(i);//计算列宽总和 } RECTrectList; listMain->GetWindowRect(&rectList);//获得列表框的窗口区域 if(intWidth<(rectList.right-rectList.left))//使列表项充溢列表框窗口 { intWidth=(rectList.right-rectList.left-intWidth)/colSum; listMain->SetColumnWidth(i,listMain->GetColumnWidth(i)+intWidth); } returnTRUE;}FillList函数用于向列表框中添加记录BOOLCADOConn::FillList(CListCtrl*listMain,intColOpenEnd){ inti,iType,iRow=0,listWidth=0; _variant_tvIndex;//var类型索引 longlMax=0; lMax=m_pRecordset->Fields->Count;//记录集字段数目 vIndex.vt=VT_I2; listMain->DeleteAllItems();//删除列表控件各列的值 if(!m_pRecordset->adoEOF)//遍历记录集 { MoveFirst();//首条记录 while(!m_pRecordset->adoEOF) { for(i=0;i<lMax;i++) { CStringstrValue=""; vIndex.iVal=i;//字段索引 //获得字段类型 iType=m_pRecordset->Fields->GetItem(vIndex)->GetType(); switch(iType) { caseado_Field_Str: caseado_Field_Text://文本 strValue=GetValueString(i,0);//获得文本值 break; caseado_Field_Long://长整型 strValue=GetValueLongStr(i,0);//获得长整值并转换为文本 break; caseado_Field_Int://Int型 strValue=GetValueIntStr(i,0);//获得INT值并转换为文本 break; caseado_Field_Float://Float型 strValue=GetValueFloatStr(i,0,2);//获得Float值并转换为文本 break; caseado_Field_Double://Double型 strValue=GetValueDoubleStr(i,0,2);//获得Double值并转换为文本 break; caseado_Field_Byte://Byte型 strValue=GetValueByteStr(i,0);//获得Byte值并转换为文本 break; caseado_Field_Date://日期时间型 strValue=GetValueString(i,0);//获得日期时间值并转换为文本 break; default: strValue=""; break; } if(m_DataType==2)//Excel文件 strValue=GetValueString(i,0); if(i==0)//第一列 listMain->InsertItem(iRow,strValue,0);//添加行 else listMain->SetItemText(iRow,i,strValue);//设置行值 } m_pRecordset->MoveNext();//下一记录 iRow=iRow+1; } MoveFirst();//移向记录集开头 } if(listMain->GetItemCount()>0)//列表框含有列 { if(ColOpenEnd>0)//要绽开的列 { for(inti=0;i<ColOpenEnd;i++) { listMain->SetColumnWidth(i,LVSCW_AUTOSIZE);//自动设置列宽 listWidth=listMain->GetColumnWidth(i);//获得列宽 listMain->SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER);//依据列标题设置列宽 if(listWidth<listMain->GetColumnWidth(i))//依据列标题设置的列宽若小于自动设置的列宽 listMain->SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER); } } else { listMain->SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER);//依据列标题设置列宽 } } else//表中没有列 { for(i=0;i<lMax;i++) { listMain->SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER); listWidth=listWidth+listMain->GetColumnWidth(i); } RECTrectList; listMain->GetWindowRect(&rectList); if(listWidth<(rectList.right-rectList.left)) { listWidth=(rectList.right-rectList.left-listWidth)/11; listMain->SetColumnWidth(i,listMain->GetColumnWidth(i)+listWidth); } } returnTRUE;}5.1.4数据库表的操作类CtablePartInfo由于本项目模拟分布式数据库,对数据库部分表进行了分片、支配等冗余设计。因此,对数据库的增、删、改、查要制定确定的规则,来保证数据的一样性,而这种规则不因为表的不同而不同。为此,我们设计了CtablePartInfo来统一的执行这种规则。classtablePartInfo:publicCWnd{public: tablePartInfo(); tablePartInfo(CString_tableName); ~tablePartInfo();public: //依据表名tableName获得表的分片和支配信息 voidGetTablePartInfo(); boolOperationOpen(CStringstrSQL,intnColumn); //依据表的分片和支配信息,按增加规则执行数据库插入操作 boolOperationAdd(CStringstrSQL); //依据表的分片和支配信息,按增加规则执行数据库修改操作 boolOperationModify(CStringstrSQL); //依据表的分片和支配信息,按增加规则执行数据库查询操作 boolOperationSelect(CStringstrSQL); boolOperationSelect(CStringstrSQL,intnColumn); boolOperationSelectInital(CStringstrSQL,intnColumn); boolOperationSelectInital(CStringstrSQL); //依据表的分片和支配信息,按增加规则执行数据库删除操作 boolOperationDelete(CStringstrSQL); //处理总站或者区域站点故障 voidHandleError(boolsuccess,intarea);public: intpart; intcopy; CListCtrl*m_list; CStringtableName; CStringstrIP; boolIsDone1; boolIsDone2; CStringErrorMessage;};下面以boolOperationAdd(CStringstrSQL)为例介绍了为维护数据库一样性,对数据库更新规则的详细实现。booltablePartInfo::OperationAdd(CStringstrSQL){ boolsuccess=true;//用于推断SQL语句是否执行成功 //首先更新总站数据库中的相应记录,因为全部的信息都会在总公司中存在 CADOConnadoMain(3); success=adoMain.ExecuteSQL(strSQL,0); HandleError(success,0);//处理执行结果,执行故障则给出报错信息 if(success)//总站执行成功,接着进行区域站点的操作 { if(0==m_globalAreaInt)//主站用户添加数据 { if(1==copy)//冗余支配的信息,同步各个区域站点数据 { CADOConnadoIP(3); CStringsqlstr="select*fromIPInfowherearea!=0"; adoIP.Open(sqlstr); //这里只有海淀和朝阳两个站点,所以预先申请两个CADIConn对象 CADOConnadoAcess1; CADOConnadoAcess2; inti=0; //循环更新每个区域站点 while(!adoIP.adoEOF()) { i++; strIP=IPAddress; IPAddress="\\\\"+adoIP.GetValueString(1,0); if(1==i)//处理海淀区数据库 { success=adoAcess1.ExecuteSQL(strSQL,1); HandleError(success,1); if(!success)//区域站点没有添加成功,这时总站撤销事务 { adoMain.m_pConnection->RollbackTrans(); adoMain.WriteLog(ErrorMessage,0); } //区域站点添加成功,需等待区域添加成功再提交事务 } if(2==i&&success)//区域站点添加成功,处理朝阳区 { success=adoAcess2.ExecuteSQL(strSQL,2); HandleError(success,2); if(!success)//区域站点没有添加成功 { adoMain.m_pConnection->RollbackTrans();//总站撤销事务 adoMain.WriteLog(ErrorMessage,0); adoAcess1.m_pConnection->RollbackTrans();//区域撤销事务 adoAcess1.WriteLog(ErrorMessage,1); } else//区域站点添加成功 { //总站和区域站点同时提交事务 adoAcess1.m_pConnection->CommitTrans(); adoAcess2.m_pConnection->CommitTrans(); adoMain.m_pConnection->CommitTrans(); } } adoIP.MoveNext(); IPAddress=strIP; } adoIP.ExitConnect(); adoAcess1.ExitConnect();//区域站点关闭数据库连接 adoAcess2.ExitConnect(); } else//数据没有copy则不用更新区域站点数据,总站提交事务 { adoMain.m_pConnection->CommitTrans(); } } else//分站用户添加数据 { if(1==part)//数据表分片,向本地添加数据 { CADOConnadoAcess; success=adoAcess.ExecuteSQL(strSQL); HandleError(success,m_globalAreaInt); if(!success)//区域站点没有添加成功 {//总站撤销事务,写下撤销事务日志 adoMain.m_pConnection->RollbackTrans(); adoMain.WriteLog(ErrorMessage,0); } else//区域站点添加成功 { //总站和区域站点同时提交事务 adoAcess.m_pConnection->CommitTrans(); adoMain.m_pConnection->CommitTrans(); } adoAcess.ExitConnect();//区域站点关闭数据库连接 } else//数据表没有分片,则提交总站事务 { adoMain.m_pConnection->CommitTrans(); } } } adoMain.ExitConnect();//总站关闭数据库连接 returnsuccess;}5.2界面窗口设计系统主框架是运用MFC创建向导创建的基于对话框的应用程序,工程名为“ShopManage”。5.2.1系统启动登录开发系统启动时,首先弹出登录对话框,用户登录后,依据用户的权限显示主界面窗口或是销售开单窗口。系统启动时,首先运行的是CShopManageApp类的InitInstance函数,在这里创建登陆对话框,登陆后依据用户的权限弹出相应的对话框窗口。InitInstance函数的实现代码如下。BOOLCShopManageApp::InitInstance(){ MainIP="10.108.13.83"; IPAddress=MainIP; IPAddressOrigin=MainIP; AfxEnableControlContainer(); CDlgLogodlgLog;//登录对话框 CShopManageDlgdlg;//主对话框 CDlgXiaoShouKanDandlgXiao;//销售开单对话框 inti; CStringstrSql; if(dlgLog.DoModal()!=IDOK)//登录失败 ::exit(0);//退出程序 CADOConnadoMain(3); strSql="select*fromAdminInfowherecode='"; strSql=strSql+dlgLog.strNo+"'"; adoMain.Open(strSql);//执行查询语句 if(!adoMain.adoEOF())//结果集不为空 { if(adoMain.MoveFirst()) { i=adoMain.GetValueInt(2); if(i==2)//销售员 { m_pMainWnd=&dlgXiao; dlgXiao.DoModal();//销售开单对话框 } else//管理员 { dlg.strNo=dlgLog.strNo;//管理员ID dlg.strName=dlgLog.strName;//管理员姓名 m_pMainWnd=&dlg; dlg.DoModal();//主对话框 } } } returnFALSE;}登录用户的验证操作在登录对话框类CDlgLogo的“确定”按钮响应函数OnOK中实现。voidCDlgLogo::OnOK(){ //TODO:Addextravalidationhere UpdateData(TRUE); CStringstrSql; CADOConnadoMain(3);//数据连接对象,用户信息表只有总站上有,所以连接SQL数据库 strSql="select*fromAdminInfowherecode='"; strSql=strSql+m_str1+"'andpwd='"; strSql=strSql+m_str2+"'"; adoMain.OpenLogo(strSql);//执行查询 if(!adoMain.adoEOF())//结果不为空 { strName=adoMain.GetValueString(1,0);//用户姓名 strNo=m_str1;//用户ID m_globalArea=adoMain.GetValueString(7,0);//用户区域 m_globalAreaInt=adoMain.GetValueInt(7); CDialog::OnOK();//关闭对话框 //依据用户区域标记获得区域站点的ip地址 CADOConnadoIP(3); CStringsqlstr="select*fromIPInfowherearea="+m_globalArea; adoIP.OpenLogo(sqlstr);//执行查询 if(!adoIP.adoEOF())//结果不为空 { IPAddress="\\\\"+adoIP.GetValueString(1,0); IPAddressOrigin="\\\\"+adoIP.GetValueString(1,0); } //写登录日志信息 adoMain.WriteLog1(m_str1); adoMain.WriteLog(strSql); adoIP.WriteLog(sqlstr); adoIP.ExitConnect(); } else MessageBox("密码或用户ID错误!","提示",MB_OK|MB_ICONWARNING); adoMain.ExitConnect();}5.2.2主界面对话框设计系统创建的是基于对话框的应用程序,因此系统的主界面是一个对话框窗口。系统中为对话框窗口添加了菜单项,为了便利进行常用操作,在对话框中还添加了一些位图按钮。为对话框添加菜单栏,首先须要在工程的资源管理器重添加设计菜单项,然后在对话框的属性对话框中,在Menu下拉列表框中,选择设计的菜单资源ID即可。按钮控件则干脆添加到主对话框模板中,须要设置Flat属性。在CShopManageDlg类的头文件中,声明CMyMenu对象,并将按钮控件的类型设置为CMyButton,代码如下。classCShopManageDlg:publicCDialog{//Constructionpublic: CShopManageDlg(CWnd*pParent=NULL); //standardconstructor CMyMenum_menu; CStringstrNo,strName; CMyButton m_ctrWarning; CMyButton m_ctrStore;……};在CShopManageDlg类的初始化函数OnInitDialog中,初始化菜单和位图按钮的设置,这里菜单和按钮的设置分别接受自定义扩展类CMyMenu和CMyButton,它们对基本菜单和按钮控件的外观作了定制,从而美化了程序界面。5.2.3通用报表对话框设计开发系统能够生成多种统计报表,在系统开发中,设计了一个通用的报表对话框,这样就简化了程序开发。在通用报表对话框资源模板中,添加了一个列表控件用于显示报表数据,一个静态文本控件用于显示报表标题

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论