第11章-数据库访问方式-郑佳峰_第1页
第11章-数据库访问方式-郑佳峰_第2页
第11章-数据库访问方式-郑佳峰_第3页
第11章-数据库访问方式-郑佳峰_第4页
第11章-数据库访问方式-郑佳峰_第5页
已阅读5页,还剩114页未读 继续免费阅读

下载本文档

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

文档简介

数据库访问技术

第11章11.1数据库访问方式11.2ODBC访问SQLServer技术

11.3DAO访问Access数据库

11.4ADO访问Access数据库主要内容11.1数据库访问方式11.1.2DAO访问11.1.3ADO访问11.1.1ODBC访问11.1.4ADO.NET访问模式对话框根底1.ODBC根本概念2.ODBC的工作原理3.ODBC的结构4.MFC的ODBC类简介1、对话框根本概念

开放式数据库互联〔OpenDataBaseConnectivity,简称ODBC〕实际上是一个数据库访问库,可以使应用程序直接操纵数据库中的数据,具有数据库的独立性,ODBC是微软公司WOSA〔WindowsOpenServiceArchitecture〕的组成局部,是微软公司提出的开放式数据库互联的标准接口,用户可以通过加载连接到数据库的驱动程序来建立与各种数据库的连接,使用ODBC不仅可以访问Access、SQLServer、OracleSybase、LotusNotes等数据库,而且可以访问Excel电子表格以及ASCII数据文件等非数据库对象,这正是ODBC的独特之处。一个基于ODBC的应用程序对数据库的操作不依赖于任何DBMS,并且不直接与DBMS打交道,所有的数据库操作由对应的DBMS的ODBC驱动程序完成,使用ODBC和MFC的ODBC的类,可以访问任何数据源,包括本地或远程的。16位和32位的ODBC驱动程序对于很大范围的数据源都是有效的,也就是说,不管是FoxPro、Access还是Oracle数据库,均可用ODBCAPI进行访问。由此可见,ODBC的最大优点是以统一的方式处理所有的数据库。1、对话框根本概念ODBC通过使用驱动程序〔Driver〕提供了很好的数据库独立性,驱动程序与具体的数据库有关。这样,通过ODBC开发的数据库应用程序,如果想更换所使用的数据库,移植到其他的数据库平台是非常容易的。例如以前的应用程序使用的是Access数据库,现在希望将其移植到SQLServer数据库上,只需将应用程序改换一下驱动程序即可,也就是说应用程序不再使用Access数据库的ODBC驱动程序,而使用SQLServer数据库的ODBC驱动程序,很容易移植到不同的数据库平台上。1、对话框根本概念2.ODBC的工作原理一个完整的ODBC由以下几个部件组成:①应用程序(Application)。②ODBC管理器(Administrator)。该程序位于Windows控制面板(ControlPanel)的32位ODBC内,其主要任务是管理安装的ODBC驱动程序和管理数据源。

2.ODBC的工作原理③驱动程序管理器(DriverManager)。驱动程序管理器包含在ODBC32.DLL中,对用户是透明的,其任务是管理ODBC驱动程序,是ODBC中最重要的部件。④ODBCAPI。⑤ODBC驱动程序。是一些DLL,提供了ODBC和数据库之间的接口。⑥数据源。数据源包含了数据库位置和数据库类型等信息,实际上是一种数据连接的抽象。各部件之间的关系如图11-1所示

图11-1ODBC各部件关系图应用程序要访问一个数据库,首先必须用ODBC管理器注册一个数据源,管理器根据数据源提供的数据库位置、数据库类型及ODBC驱动程序等信息,建立起ODBC与具体数据库的联系。只要应用程序将数据源名提供给ODBC,ODBC就能建立起与相应的数据库连接。在ODBC中,ODBCAPI不能直接访问数据库,必须通过驱动程序管理器与数据库交换信息。驱动程序管理器包含在ODBC.DLL或ODBC32.DLL中。驱动程序管理器负责将应用程序对ODBCAPI的调用传递给正确的驱动程序,而驱动程序在执行相应操作后,将结果通过驱动程序管理器返回给应用程序。在访问ODBC数据源时需要ODBC驱动程序的支持,在32位Windows环境中,大都安装了SQLServer、Access、Paradox、dBase、FoxPro、Excel、Oracle和MicrosoftText等驱动程序。ODBC是通过使用驱动程序〔Driver〕提供数据库独立性的。驱动程序是ODBC的一个重要组件,它是支持ODBC函数调用的模块,通常是一个DLL,并与具体的数据库有关,例如操作Access数据库要使用Access的ODBC驱动程序,操作SQLServer数据库必须使用SQLServer的ODBC驱动程序。应用程序是通过调用驱动程序所支持的函数来操作数据库的,因此,如果应用程序要操作不同类型的数据库,就要动态连接到不同的驱动程序上。许多应用程序开发软件都提供ODBC接口,VisualC++也不例外,ODBC接口以SQL作为标准的查询语言来存取连接到的数据源,它允许单个应用同时访问不同的数据库管理系统〔DBMS〕,这使应用程序开发人员不必关心所操作的数据库管理系统,而能完成应用开发。VisualC++从2.0就开始包含ODBC库和头文件,并在MFC类库中包含了基于ODBC的扩展数据库类,它封装了使用ODBC的细节,节省了开发人员大量工作,使ODBC应用程序的开发变得非常容易。3.ODBC的结构ODBC调用主要由四个层次组成,如图11-2所示。

图11-2ODBC四层结构〔1〕第一层:ODBC应用软件〔如VisualC++〕,它通过ODBC函数向数据库发送SQL语句并处理SQL返回结果。3.ODBC的结构〔2〕第二层:ODBC驱动管理程序,它负责管理和装载驱动程序,其作用是:①用ODBC.INI文件映射数据源到特定驱动程序。②处理ODBC的初始化调用。③为每个驱动程序提供ODBC函数入口。④提供ODBC调用参数和顺序。3.ODBC的结构〔3〕第三层:ODBC驱动程序,处理ODBC函数调用,提交SQL请求给特定的数据源并返回结果给应用程序,如果必要,它还修改SQL请求,使得SQL请求的语法与特定数据库的语法一致。〔4〕第四层:数据源,数据源是指要存取的数据及其相关的操作系统、数据库管理系统和网络系统。3.ODBC的结构4.MFC的ODBC类简介

MFC的ODBC类对较为复杂的ODBCAPI进行了封装,提供了简化的调用接口,从而大大方便了数据库应用程序开发。程序员不必了解ODBCAPI和SQL的具体细节,利用ODBC类即可完成对数据库的大局部操作。MFC的ODBC类主要包括:CDatabase类:主要功能是建立与数据源的连接。CRecordset类:该类代表从数据源选择的一组记录〔记录集〕,程序可以选择数据源中的某个表作为一个记录集,也可以通过对表的查询得到记录集,还可以合并同一数据源中多个表的列到一个记录集。通过该类可对记录集中的记录进行滚动、修改、增加和删除等操作。CRecordView类:提供了一个表单视图,它与某个记录集直接相连,利用对话框数据交换机制(DDX)在记录集与表单视图的控件之间交换数据,该类支持对记录的浏览和更新,在销毁时,会自动关闭与之相联系的记录集。CFieldExchange类:支持记录字段数据交换〔DFX〕,即记录集字段数据成员与相应数据库的表字段之间的数据交换,该类功能与CDataExchange类的对话框数据交换功能类似。CDBException类:代表ODBC类产生的异常。MFC的ODBC类主要包括:

概括起来:CDatabase针对某个数据库,负责

连接数据源;CRecordset针对数据源中的记录集,

负责对记录的操作;CRecordView负责界面;CFieldExchange负责CRecordset

与数据源的数据交换。MFC的ODBC类主要包括:

1.什么是DAO2.DAO与ODBC的比较3.DAO的特色11.1.2DAO访问什么是DAODAO〔DatabaseAccessObject〕使用MicrosoftJet数据库引擎来访问数据库,提供了一种新的数据库编程方式,力求使数据库编程更为简单方便。MicrosoftJet为Access和VisualBasic提供了数据引擎。因此,如果要直接访问由Microsoft产品创立的数据库,如Access数据库,那么DAO是最适宜的,它会使数据库的访问速度更快,更易于使用。

与ODBC一样,DAO提供了一组API供编程使用,MFC也提供了一组DAO类,封装了底层的API,大大简化了程序的开发,利用MFC的DAO类,用户可以编写独立于DBMS的应用程序。DAO是从VisualC++4.0开始引入,一般来说,DAO类提供了比ODBC类更广泛的支持,一方面,只要有ODBC驱动程序,使用MicrosoftJet的DAO就可以访问ODBC数据源。另一方面,由于DAO是基于MicrosoftJet引擎的,因而在访问Access数据库〔*.MDB文件〕时具有更好的性能。同时DAO也可直接用于其他一些文件访问,但性能不佳,包括以下几种:①文本文件:按某种方式格式化的文本文件,如标准分界文件,它使用逗号分界符隔离字段,回车分界符别离每条记录,用双引号限定文本。②MicrosoftExcel表格文件:DAO可访问用MicrosoftExcel创立的电子表格文件。

③Lotus表格文件:DA0可访问WKS、WK1、WK3以及WK4文件类型的Lotus表格文件。④ISAM数据库ISAM〔索引顺序访问方式〕数据库主要包括dBASE、FoxBase、FoxPro等,DAO可访问它们的数据库文件。2.DAO与ODBC的比较

如果利用VisualC++开发数据库应用,究竟选择ODBC方式还是DAO方式经常是困扰开发者的一个问题。在此,我们对ODBC和DAO进行一些比较,以帮助开发者在实际的数据库开发中进行决策,尽量做到既保证应用程序的性能,又使编程工作相对轻松。DAO与ODBC的比较①二者都支持对各种ODBC数据源的访问。虽然二者使用的数据引擎不同,但都可以满足用户编写独立于DBMS应用程序的要求。②DAO提供了与ODBC功能相似的MFC类。例如,DAO的CDaoDatabase类对应ODBC的CDatabase类,CDaoRecordset对应CRecordset,CDaoRecordView对应CRecordView,CDaoException对应CDBException,这些对应的类功能相似,它们的大局部成员函数都是相同的。③应用程序向导和类向导对使用DAO和ODBC对象的应用程序提供了类似的支持。3.DAO的特色

DAO可以通过ODBC驱动程序访问ODBC

数据源。但DAO是基于MicrosoftJet引擎的,通过该引擎,DAO可以直接访问Access、FoxPro、dBASE、Paradox、Excel和LotusWK等数据.CDaoDatabase

类可以直接与这些数据库进行连接,而不必在ODBC管理器中注册DSN。

支持DDL是DAO对数据库编程良好支持的一个重要表达。DDL(DataDefinitionLanguage)在SQL术语中叫做“数据定义语言〞,它用来完成生成、修改和删除数据库结构的操作。ODBC类只支持DML〔DataManipulationLanguage,数据操作语言〕,不支持DDL,所以用ODBC类只能完成数据的操作,不涉及数据库的结构。要执行DDL操作,只有通过ODBCAPI。而DAO类同时提供了对DML和DDL的支持,这意味着程序可以使用DAO类方便的创立数据库以及修改数据库的结构。

DAO的另一个重要特色在于它对Access数据库提供了强大的支持。由于DAO是基于MicrosoftJet引擎的,所以DAO对Access数据库的支持更多一些,例如,调用CDaoDatabase::Create可以创立一个MDB文件。利用应用程序向导和类向导,用户可以方便地开发出性能优良的基于DAO的Access数据库应用程序。11.1.3ADO访问ADO是Windows环境比较流行的客户端数据库访问技术,建立在OLEDB底层技术之上的高级编程接口。一方面具有强大的数据处理能力,可以处理各种不同类型的数据源、分布式数据等,另一方面具有极其简单、易用的编程接口,得到了越来越多的应用。ADO数据库访问技术实际上就是一组Automation对象组件,因此ADO的使用和其它任何Automation对象的使用没有区别。ADO访问技术中最主要的三个对象分别是:Connection、Command和Recordset,分别代表“连接对象〞、“命令对象〞和“记录集对象〞。本章第4节将进一步讨论在VS2023开发环境中如何实现ADO的数据库访问。11.1.4ADO.NET访问除了ODBC、DAO和ADO访问方式外,还有时下流行的基于.NET平台的ADO.NET数据库访问技术,它是.NET环境下连接数据库的重要技术,但采用该技术开发的应用程序必须要.NET运行环境支持。和ADO访问技术类似,ADO.NET是.NET框架下一组操作数据库的对象组件〔.NET组件〕,其工作流程如图11-3所示。通过这些对象可以完成数据库连接、数据查看、插入、更新和删除以及数据库的关闭等根本操作。ADO.NET数据库访问根本流程图11-3ADO.NET数据库访问根本流程ADO.NET主要有以下六个对象:〔1〕Connection:使用一个连接字符串建立与特定数据源的连接;〔2〕Command:针对数据源执行SQL命令;〔3〕DataReader:从数据源获取只读的数据;〔4〕DataAdapter:在DataSet和数据源之间传递数据;〔5〕DataSet:包含一个或多个DataTable对象组成的集合,是一个容器;〔6〕DataView:实现对DataSet中数据进行排序、过滤和查找等操作。以上简要介绍了Windows平台下数据库访问的主要技术及其特点,开发人员可根据具体情况选择适宜的数据库访问技术,使开发效率和系统性能到达最正确。11.1数据库访问方式11.2ODBC访问SQLServer技术

11.3DAO访问Access数据库

11.4ADO访问Access数据库

主要内容11.2ODBC访问SQLServer技术11.2.1记录集与记录视11.2.2数据库操作11.2.3记录集的操作11.2.4ODBC应用举例11.2.5多表操作应用举例1.记录集CRecordset类代表一个记录集。在多任务操作系统或网络环境中,多个用户可以共享同一个数据源。共享数据的主要问题是如何协调各个用户对数据源的修改。对基于MFC的ODBC应用程序来说,主要取决于应用程序所采用的记录集的种类。根据其它应用改变数据后处理方式的差异。记录集可分为快照〔Snapshot〕和动态集〔Dynaset〕两种。〔1〕快照记录集提供了对数据的静态视。如同对数据源的某些记录照了一张照片,当其它用户改变记录时〔如修改、添加和删除〕,快照中的记录不受影响,除非通过CRecordset::Requery重新查询。对于产生报表、执行计算不需要中途变动的任务,快照是最理想的方式。快照的这种静态特性是相对于其它用户来说的,用户自身对记录的修改和删除,快照能够及时反映,但对新增记录,只有调用Requery后才能正确反映到快照中。〔2〕动态集提供了数据的动态视。当其它用户修改或删除记录时,动态集会自动更新。当用户移动到修改正的记录时,会看到其他用户所作的修改;当记录被其他用户删除时,动态集会跳过记录集中删除的局部,这样也看到其他用户的删除;但对其他用户添加的记录,只有调用Requery后,新增加的记录才会在动态集中反映出来。应用程序自身对记录的修改、添加和删除会自动反映在动态集中。当数据自身具有动态特性时,使用动态集是最理想的。光标库〔CursorLibrary〕是处于ODBC驱动程序管理器和驱动程序之间的动态链接库〔ODBCCR32.DLL〕,主要功能是为快照和底层驱动程序提供双向滚动能力,负责管理快照记录的缓冲区。快照记录缓冲区只能反映应用程序自身对记录所做的修改和删除,不能反映其他用户对记录的更改。快照是一种静态光标〔StaticCursor〕,其特点是只有滚动到某个记录才能取得该记录的数据。如果要保证所有的记录都被快照,必须从记录集的开始滚动到末尾,然后再滚动到某一记录,显然从开始滚动到末尾增加了系统的额外开销,降低了性能。与快照不同,动态集不是用光标库维持缓冲区来存取记录,而是一种键集驱动光标〔Keyset-DrivenCursor〕,当翻开动态集时,驱动程序保存记录集中每个记录的键,只要光标在动态集中滚动,驱动程序就会通过键来从数据源中检取当前记录,从而保证选取的记录与数据源同步。快照和动态集具有一个共同特点,在建立记录集后,记录集中的成员就已经确定,这也就是快照和动态集都不能反映其他用户添加记录的原因所在CRecordView〔记录视图〕是CFormView的派生类,它提供了一个表单视图来显示当前记录,用户可以通过表单视图显示当前记录,通过记录视图,可以修改、添加和删除数据。用户一般需要创立一个CRecordView的派生类,并在对应的对话框模板中添加控件。

2.记录视图

3.记录集与记录视图的关系记录视图是一个连接到记录集的窗体视图类,通过使用DDX数据交换机制在表单控件和记录集之间交换数据。当用户在控件中输入数据时,记录视图的DDX〔对话框数据交换〕把数据移到记录集的数据成员中,这些数据成员又被记录集的RFX〔记录字段交换〕绑定到数据库的字段上。在应用程序向导生成应用程序的过程中,如果指定了数据库视图应用程序,应用程序向导将产生一个CRecordView派生类和一个CRecordset的派生类,两者在运行时被连接起来,而且生成一个空的对话框模板。这样,用户只需要在对话框模板上添加控件,并把这些控件与记录集数据成员做匹配,而不需要额外编程,简化了数据库应用开发过程。11.2.2数据库操作建立与数据源的连接,首先应构造一个CDatabase对象,然后调用CDatabase的Open成员函数,建立数据库连接,Open函数原型如下:virtualBOOLOpen(LPCTSTRlpszDSN,BOOLbExclusive=FALSE,BOOLbReadOnly=FALSE,LPCTSTRlpszConnect=“ODBC;〞,BOOLbUseCursorLib=TRUE);throw(CDBException,CMemoryException);参数lpszDSN指定了数据源名〔构造数据源的方法将在后面介绍〕,在lpszConnect参数中也可包括数据源名,此时lpszDSN必须为NULL,假设在函数中未提供数据源名且使lpszDSN为NULL,那么会显示一个数据源对话框,用户可以在该对话框中选择一个数据源。参数bExclusive说明是否独占数据源,该参数一般设是FALSE,说明数据源是共享的。参数bReadOnly假设为TRUE那么对数据源的连接是只读的。参数lpszConnect指定了一个连接字符串,连接字符串中可以包括数据源名、用户帐号〔ID〕和密码等信息,字符串中的“ODBC〞表示要连接到一个ODBC数据源上。参数bUseCursorLib假设为TRUE,那么会装载光标库,否那么不装载,快照需要光标库,动态集不需要光标库。假设连接成功,函数返回TRUE,否那么返回FALSE。11.2.3记录集的操作建立记录集,首先构造一个CRecordset派生类对象,然后调用Open成员函数查询数据源中的记录并建立记录集,其函数声明如下:CRecordset(CDatabase*pDatabase=NULL);参数pDatabase指向一个CDatabase对象,用来获取数据源。如果pDatabase为NULL,那么会在Open函数中自动构建一个CDatabase对象。如果CDatabase对象还未与数据源连接,那么在Open函数中会建立连接,连接字符串由成员函数GetDefaultConnect提供。Open成员函数使用指定SQL语句查询数据源中的记录并按指定的类型和选项建立记录集,其函数声明如下:virtualBOOLOpen(UINTnOpenType=AFX_DB_USE_DEFAULT_TYPE,LPCTSTRlpszSQL=NULL,DWORDdwOptions=none);throw(CDBException,CMemoryException);参数nOpenType说明了记录集的类型,如表11-1所示,如果要求的类型驱动程序不支持,那么该函数将产生一个异常。参数lpszSQL是一个SQL的SELECT语句,或是一个表名,用于查询,如果该参数为NULL,那么函数会调用GetDefaultSQL获取缺省的SQL语句。参数dwOptions可以是一些选项组合,常用选项在表11-2中列出。假设创立成功那么返回TRUE,否那么返回FALSE。通过合理地安排SQL语句和表名,Open函数可以非常灵活地查询数据源中的记录,可以合并多个表的字段,也可以只选择记录中的某些字段,还可以对记录进行过滤和排序。如果在调用Open时只提供了表名,框架规定,如果只提供了表名,那么选择列的信息从DoFieldExchange的RFX语句里提取,防止SELECT语句缺少选择列参数rfx-field-list。建立记录集后,用户可以随时调用Requery成员函数来重新查询和建立记录集,该函数有两个目的:①使记录集能反映用户对数据源的修改②按照新的过滤或排序方法查询记录,并重新建立记录集在调用Requery之前,需要调用CanRestart函数判断记录集是否支持Requery操作。再者,Requery只能在成功调用Open后调用,因此在Requery之前还需要调用IsOpen判断记录集是否已建立,下面给出Requery函数声明:virtualBOOLRequery();throw(CDBException,CMemoryException);返回TRUE说明记录集建立成功,否那么返回FALSE,假设函数内部出错那么产生异常。

CRecordset类有两个公共数据成员m_strFilter和m_strSort用来设置对记录的过滤和排序。在调用Open或Requery之前,如果这两个数据成员指定了过滤或排序条件,那么Open和Requery将按这两个数据成员指定的过滤和排序来检索数据源。〔1〕成员m_strFilter用于指定过滤器,m_strFilter实际上包含了SQL的WHERE子句的内容,但它不含WHERE关键字。〔2〕成员m_strSort用于指定排序,m_strSort实际上包含了ORDERBY子句的内容,但它不含ORDERBY关键字。事实上,Open函数在构造SELECT语句时,会把m_strFilter和m_strSort的内容放入SELECT语句的WHERE和ORDERBY子句中。如果在Open的lpszSQL参数中已包括了WHERE和ORDERBY子句,那么m_strFilter和m_strSort必须为空。调用无参数成员函数Close关闭记录集,在调用Close函数后,程序可以再次调用Open建立新的记录集。CRecordset的析构函数会调用Close函数,所以当删除CRecordset对象时记录集也随之关闭。2.滚动记录CRecordset提供了几个成员函数用来在记录集中滚动,当用这些函数滚动到一个新记录时,框架会自动把新记录的内容拷贝到数据成员中。

voidMoveNext();

//前进一个记录

voidMovePrev();

//后退一个记录

voidMoveFirst();

//滚动到记录集中的第一个记录voidMoveLast();

//滚动到记录集中的最后一个记录voidSetAbsolutePosition(longnRows);

SetAbsolutePosition函数用于滚动到由参数nRows指定的绝对位置,如果nRows为-1时,函数就滚动到记录集的末尾。注意,该函数不会跳过被删除的记录

3.修改、添加和删除记录(1)修改当前记录①调用Edit函数进入编辑模式,该函数会把当前数据成员的内容保存在一个缓冲区中,一方面可以和数据成员作比较以判断哪些字段被改变了,另一方面在必要的时候可以恢复数据成员原来的值。如果再次调用Edit,记录集将从缓冲区中恢复数据成员,而且程序仍处于编辑模式。调用Move(AFX_MOVE_REFRESH)或Move(0)可退出编辑模式,同时该函数会从缓冲区中恢复数据成员。提示:不要在一个空的记录集中调用Edit,否那么会产生异常。②设置数据成员的新值。③调用Update把变化后的记录写入数据源并结束编辑模式。(2)添加新记录①调用AddNew函数进入添加模式,该函数把所有的数据成员都设置成NULL〔在数据库术语中,NULL是指没有值,这和C++中的NULL不同)。与Edit一样,AddNew会把当前数据成员的内容保存在一个缓冲区中,在必要的时候,程序可以再次调用AddNew取消添加操作并恢复数据成员原来的值,调用后,程序仍处于添加模式。调用Move(AFX_MOVE_REFRESH)可退出添加模式,同时该函数会从缓冲区中恢复数据成员。②设置数据成员。③调用Update把数据成员中的内容作为新记录写入数据源,结束添加过程。④如果记录集是快照,那么在添加一个新记录后,还需要调用Requery重新查询,因为快照无法反映添加操作。(3)删除当前记录①调用Delete函数,该函数同时给记录集和数据源中当前记录加上删除标记。提示:不要在一个空记录集中调用Delete,否那么会产生一个异常。②滚动到另一个记录上以跳过删除记录。在对记录集进行更改以前,程序需要调用以下函数判断记录集是否可以更改,如果在不能更改的记录集中进行修改、添加或删除,将导致异常的产生。BOOLCanUpdate()const; //返回TRUE说明记录可修改、添加和删除BOOLCanAppend()const; //返回TRUE说明可以添加记录。11.2.4ODBC应用举例1.应用实例概述这个实例是要完成一个学生成绩管理系统的开发,数据库采用SQLServer2005。首先需要在SQLServer上创立一个名为stu_score的数据库,并创立一个学生信息数据表〔student〕,存放每个学生的信息,包括学生的学号、姓名、系别、专业、班级。此实例向读者演示了应用程序的创立、数据的遍历和查找以及添加、修改和删除数据等功能。〔1〕利用VisualC++的应用程序向导创立ODBC应用,生成与学生信息表student相对应的记录集类和视图类,存取并显示student表中的记录。〔2〕遍历学生信息表,将学生信息添加到学生信息视图中,能够按学号查找对应的学生。〔3〕实现对学生信息表的添加、修改、删除等数据操作。

1.应用实例概述

2.建立SQLServer数据库3.建立数据源4.建立应用程序

〔1〕利用“应用程序向导〞生成应用程序框架〔2〕创立视图①编译连接,如果出现“#error:平安问题:连接字符串可能包含密码?〞错误提示,请翻开“类视图〞,点击“CS11_1Set〞类节点,定位到GetDefaultConnect函数,如果不担忧程序中包含明文密码的平安性隐患,请将编译所产生的错误信息删除,重新编译;如果希望用户每次都输入密码,请将连接字符串中的密码〔“pwd=odbc;〞〕删除,然后编译运行,这时在程序启动时,会弹出一个如图11-26所示的对话框,要求用户输入连接到数据库的用户名〔odbc〕和密码〔odbc〕,才能登录到指定的数据库。②在对话框资源中添加控件翻开“资源视图〞,展开当前工程资源下的“Dialog〞节点,双击IDD_S11_1_FORM,翻开对话框编辑器,按以下步骤添加控件。●添加一个标题静态文本框,Caption属性为:学生信息●为student表的每个字段添加相应的静态文本〔Statictext〕和编辑框〔Editbox〕控件,静态文本的Caption属性分别为:学号、姓名、系别、专业、班级,编辑框控件的ID分别为IDC_SNO、IDC_SNAME、IDC_SDEPT、IDC_SPECIAL、IDC_SCLASS,如图11-28所示。

翻开“类视图〞,选择“CS11_1View〞类,定位到数据交换函数DoDataExchange,添加以下代码。提示:在VS2023中不能通过类向导将控件和记录集中的变量关联。voidCS11_1View::DoDataExchange(CDataExchange*pDX){ CRecordView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CS11_1View) DDX_FieldText(pDX,IDC_SNO,m_pSet->m_sno,m_pSet); DDX_FieldText(pDX,IDC_SNAME,m_pSet->m_sname,m_pSet); DDX_FieldText(pDX,IDC_SCLASS,m_pSet->m_sclass,m_pSet); DDX_FieldText(pDX,IDC_SDEPT,m_pSet->m_sdept,m_pSet); DDX_FieldText(pDX,IDC_SPECIAL,m_pSet->m_special,m_pSet); //}}AFX_DATA_MAP}

③将Edit控件和数据集中的字段关联

重新编译运行此程序,结果如图11-29所示。程序现在可以显示stu_score数据库中student表的当前记录,并可通过界面上端的工具栏按钮进行数据库记录的导航,包括移动第一条、上一条、下一条、最后一条记录等,当记录不能移动时,

相应按钮自动变灰,防止误操作。①添加查找功能翻开“资源视图〞,展开Menu菜单资源,双击“IDR_MAINFRAME〞,翻开菜单编辑器,在“记录〞和“查看〞之间添加一个“查找(&S)〞菜单,并在其下面增加两个菜单项,ID分别为ID_FIND_STU和ID_FIND_STU_ALL,Caption分别为“查找学生(&C)〞和“所有学生信息(&A)〞,接下来,为该工程添加一个对话框资源用于输入查找学生的学号。翻开“资源视图〞,展开工程资源,在“Dialog〞节点的按右键,在弹出的快捷菜单中,选择“添加资源〞菜单项,在弹出的“添加资源〞对话框中选择Dialog,单击“新建〞按钮,完成对话框资源的添加。选中该对话框,修改ID为IDD_FIND_STU。在对话框上添加一个静态文本、一个编辑框和两个按钮控件,其属性设置如表11-3所示,设计的最终效果如图11-31所示翻开“类向导〞,点击“添加类〞按钮,为对话框资源IDD_FIND_STU添加一个新类CFindStuDialog,基类为CDialog类,如图11-32所示,点击“完成〞,关闭“添加类向导〞对话框。在“类向导〞对话框中,为编辑框控件IDC_FIND_STU_SNO添加成员变量m_find_stu_sno,类别为Value,类型为CString,如图11-33所示。在“MFC类向导〞对话框中,选择CS11_1View类,在“对象ID〞中,为“查找学生〞菜单项ID_FIND_STU,添加COMMAND和UPDATE_COMMAND_UI消息响应函数OnFindStu和OnUpdateFindStu。为“所有学生信息〞菜单项ID_FIND_STU_ALL,添加COMMAND和UPDATE_COMMAND_UI消息响应函数OnFindStuAll和OnUpdateFindStuAll。重新编译运行应用程序,在“查找〞菜单下选择“查找学生〞,弹出如图11-35所示对话框,输入要查找的学生学号,如002,如果在记录集中找到了相应的记录,那么显示此记录,否那么,弹出消息框显示“没有找到该学生信息〞。②添加增加功能翻开“资源视图〞中Menu资源,双击IDR_MAINFRAME翻开菜单资源编辑器。在“记录〞菜单下添加菜单项,Caption为“添加记录(&)〞,ID为ID_RECORD_APPEND,如图11-36所示。在CS11_1View类中添加一个保护类型的成员变量m_bAddFlag,用于标记当前是否处于添加状态,翻开S11_1View.h文件,在类定义的保护局部添加如下代码:BOOLm_bAddFlag;在CS11_1View类的构造函数中,将其初始化为FALSE:m_bAddFlag=FALSE;翻开“类向导〞对话框,选择CS11_1View类,为“添加记录〞菜单项ID_RECORD_APPEND添加COMMAND和UPDATE_COMMAND_UI消息响应函数。点击“虚虚数〞标签,选择OnMove,点击“添加函数〞按钮,重写OnMove虚函数,如图11-37所示。11.1数据库访问方式11.2ODBC访问SQLServer技术

11.3DAO访问Access数据库

11.4ADO访问Access数据库

主要内容11.3DAO访问Access数据库11.3.1记录集与记录视11.3.2增强的数据库管理功能11.3.3DAO应用举例DAO引入了一种在ODBC体系中没有的新记录集类型:表类型记录集。它是一个完整的数据库表的直接视图,我们只能对Access数据库中的表使用表类型记录集。表类型记录集有下面一些区别于快照和动态记录集的特征。〔1〕函数CDaoRecordset::GetRecordCount返回一个近似的记录数,这个数能反映其他用户增加或删除的记录。〔2〕不能用CDaoRecordset的函数访问一个记录的绝对或百分比位置。〔3〕CDaoRecordset::Seek函数通过关键字段值定位到一条记录,但首先要调用CdaoRecordset::SetCurrentIndex函数选择索引字段。〔4〕如果往表类型记录集中添加一条记录,该记录的位置由当前索引排列的顺序决定。表类型记录集在很大程度上背离了ODBC和SQL,也就是说可以不通过查询而选择一条单独的记录;也可以通过索引找到一条记录,然后用另外一个索引来顺序移动,这和dBASE或者FoxPro的编程思路类似。

11.3.1记录集与记录视11.3.2增强的数据库管理功能VisualC++的MFC中包含的DAO类与ODBC类非常相似,前面介绍的主要ODBC类:CDatabase、CRecordset和CrecordView,在DAO类中都有与之相对应的类:CDaoDatabase、CDaoRecordset和CDaoRecordView,其中封装的成员变量和函数也类似,但它们比对应的ODBC类封装了更多的成员函数。DAO增加了一个名为CDaoWorkspace的类,当开始跟踪事务时,DAO通过CDaoWorkspace类给出了较好的粒度〔Granularity〕。下面介绍DAO类比ODBC类新增的内容。11.3.3DAO应用举例在了解了MFCDAO类以后,下面给出一个DAO应用实例,这个实例所采用的数据库是MicrosoftAccess。因为在ODBC访问数据库的应用实例中已经向大家介绍了根本的数据库操作〔如数据的添加、修改、删除等〕,本节的实例主要集中在DAO新增的功能〔如新建数据表〕的介绍,使读者体会到DAO的优势所在。1.应用实例概述本实例使用Access数据库,首先需要新建一个Access数据库test,但并不建立任何数据表,也就是建立一个没有数据表的数据库。在应用程序中新建数据表,也可以删除数据表。2.创立应用程序〔1〕启动VS2023,选择“文件|新建|工程…〞菜单项,翻开“新建工程〞对话框,选择应用程序模板为“MFC应用程序〞,在“名称〞框中输入应用程序名S11_3,在“位置〞框中输入应用程序保存的位置,如图11-49所示。2.创立应用程序

①单击“确定〞按钮,在弹出的“MFC应用程序向导〞对话框中,选择工程类型为“基于对话框〞,如图11-50所示。②其余选项采用默认值,点击“完成〞按钮,生成应用程序框架。2.创立应用程序〔2〕在对话框界面上添加控件资源翻开“资源视图〞,展开对话框资源,双击Dialog下的IDD_S11_3_DIALOG,翻开对话框编辑器,按下面步骤在对话框中修改或者添加控件。①修改IDOK按钮属性,将其Caption属性设为“新建表〞2.创立应用程序②增加两个RadioButton控件和一个CheckBox控件,两个RadioButton控件的ID分别为IDC_NEW_TABLE和IDC_DELETE_TABLE,Caption属性分别为“新建表〞和“删除表〞,CheckBox控件ID为IDC_IS_KEY,Caption属性为“是否不为空〞。③增加两个EditBox控件:ID号分别为IDC_NEWTABLE_NAME,IDC_FIELD_NAME,增加两个Combobox控件,一个ID为IDC_EXISTTABLE_NAME,并且将其位置和IDC_NEWTABLE_NAME位置重合,另一个ID为IDC_FIELD_TYPE,Type属性为:“DropList〞,Data属性为:“文本;数字;〞。添加控件后的对话框如图11-52所示,注意重合的控件只能看到最前端一个。2.创立应用程序2.创立应用程序〔4〕利用“类向导〞为控件添加消息响应函数翻开“类向导〞,在“类名〞选择CS11_3Dlg,在“命令〞标签下的“对象ID〞中列出了刚刚添加控件的ID,选择相应的控件ID添加消息响应函数,需要添加的消息响应函数如表11-5所示。2.创立应用程序2.创立应用程序

str.TrimLeft(); str.TrimRight(); if(str=="新建表") {sqlcode="createtable"+m_newtable_name+"("+m_field_name;if(m_field_type.GetCurSel()==1)sqlcode+="char(10)";if(m_field_type.GetCurSel()==0)sqlcode+="int";if(m_is_key.GetCheck()==1)sqlcode+="notnull";sqlcode+=")";m_db.Execute(sqlcode,dbFailOnError);m_existtable_name.AddString(m_newtable_name);MessageBox("新建表"+m_newtable_name+"成功!");m_newtable_name="";m_field_name="";m_is_key.SetCheck(0);UpdateData(FALSE); }2.创立应用程序

if(str=="删除表")

{CStringcurtable;

if(m_existtable_name.GetCount()!=0)

{m_existtable_name.GetLBText(m_existtable_name.GetCurSel(),

curtable);

sqlcode="droptable"+curtable;

m_db.Execute(sqlcode,dbFailOnError);

m_existtable_name.DeleteString(m_existtable_name.GetCurSel());

m_existtable_name.SetCurSel(0);

MessageBox("删除表"+curtable+"成功!");

}

elseMessageBox("当前没有表可删除!");

}

m_db.Close();

//CDialog::OnOK();

}2.创立应用程序

voidCS11_3Dlg::OnDeleteTable()

{

//TODO:Addyourcontrolnotificationhandlercodehere

//隐藏或显示相应控件

GetDlgItem(IDC_EXISTTABLE_NAME)->ShowWindow(TRUE);

GetDlgItem(IDC_NEWTABLE_NAME)->ShowWindow(FALSE);

GetDlgItem(IDC_FIELD_NAME)->ShowWindow(FALSE);

GetDlgItem(IDC_FIELD_TYPE)->ShowWindow(FALSE);

GetDlgItem(IDC_IS_KEY)->ShowWindow(FALSE);

GetDlgItem(IDC_STATIC1)->ShowWindow(FALSE);

GetDlgItem(IDC_STATIC2)->ShowWindow(FALSE);

GetDlgItem(IDOK)->SetWindowText("删除表");

GetDlgItem(IDOK)->EnableWindow(TRUE);

m_newtable_name="";

m_field_name="";

m_is_key.SetCheck(0);

UpdateData(FALSE);

}2.创立应用程序

voidCS11_3Dlg::OnNewTable()

{

//TODO:Addyourcontrolnotificationhandlercodehere

//隐藏或显示相应控件

GetDlgItem(IDC_EXISTTABLE_NAME)->ShowWindow(FALSE);

GetDlgItem(IDC_NEWTABLE_NAME)->ShowWindow(TRUE);

GetDlgItem(IDC_FIELD_NAME)->ShowWindow(TRUE);

GetDlgItem(IDC_FIELD_TYPE)->ShowWindow(TRUE);

GetDlgItem(IDC_IS_KEY)->ShowWindow(TRUE);

GetDlgItem(IDC_STATIC1)->ShowWindow(TRUE);

GetDlgItem(IDC_STATIC2)->ShowWindow(TRUE);

GetDlgItem(IDOK)->SetWindowText("新建表");

GetDlgItem(IDOK)->EnableWindow(FALSE);

}2.创立应用程序

voidCS11_3Dlg::OnChangeFieldName()

{

//TODO:IfthisisaRICHEDITcontrol,thecontrolwillnot

//sendthisnotificationunlessyouoverridetheCDialog::OnInitDialog()

//functionandcallCRichEditCtrl().SetEventMask()

//withtheENM_CHANGEflagORedintothemask.

//TODO:Addyourcontrolnotificationhandlercodehere

UpdateData(TRUE);

m_field_name.TrimLeft();

m_field_name.TrimRight();

GetDlgItem(IDOK)->EnableWindow(TRUE);

}

voidCS11_3Dlg::OnChangeNewtableName()

{

//TODO:IfthisisaRICHEDITcontrol,thecontrolwillnot

//sendthisnotificationunlessyouoverridetheCDialog::OnInitDialog()

//functionandcallCRichEditCtrl().SetEventMask()

//withtheENM_CHANGEflagORedintothemask.

//TODO:Addyourcontrolnotificationhandlercodehere

UpdateData(TRUE);

m_newtable_name.TrimLeft();

m_newtable_name.TrimRight();

}2.创立应用程序2.创立应用程序11.1数据库访问方式11.2ODBC访问SQLServer技术

11.3DAO访问Access数据库

11.4ADO访问Access数据库

主要内容11.4ADO访问Access数据库在掌握了MFC的ODBC编程技术〔CDatabase和CRecordset〕和DAO以后,学习ADO编程就十分容易了,因为ADO也是提供了三个主要的对象来完成数据库的访问。〔1〕Connection〔连接对象〕〔2〕Command〔命令对象〕〔3〕Recordset〔记录集对象〕

1.使用预处理指令#import2.使用MFC中的CIDispatchDriver3.直接使用COM对象提供的API函数11.4ADO访问Access数据库1.使用预处理指令#import在工程stdAfx.h文件的开头,所有include指令后,参加以下编译预处理指令:#import"C:\ProgramFiles\CommonFiles\System\ADO\msado15.dll"no_namespacerename("EOF","EndOfFile")这样在编译时,VC++会读出msado15.dll中的类型库信息,自动生成该类型库的头文件msado15.tlh和实现文件msado15.tli。这两个文件定义了ADO的所有对象和方法,以及一些枚举常量。

2.使用MFC中的CIDispatchDriver

通过读取msado15.dll的类型库信息,建立一个COleDispatchDriver类的派生类,然后通过它调用ADO对象。

3.直接使用COM对象提供的API函数下面的代码就是用COMAPI函数创立一个ADO连接对象:CLSIDclsid;HRESULThr=::CLSIDFromProgID(L"ADODB.Connection",&clsid);if(FAILED(hr)){...}::CoCreateInstance(clsid,NULL,CLSCTX_SERVER,IID_IDispatch,(void**)&pDispatch);if(FAILED(hr)){...}以上三种方法,第一和第二种类似,第一种简单,适合初学者,第三种编程麻烦,但是效率高,程序大小也小,并且对ADO的控制能力也最强。11.4.2使用#import的编程步骤

下面讨论在VisualC++中用import方法进行ADO数据库编程的具体过程。1.生成应用程序框架并初始化OLE/COM库环境首先创立标准MFC应用程序框架,选择单文档应用程序,然后在应用程序类的InitInstance成员函数中初始化OLE/COM库,添加以下代码:::CoInitialize(NULL);//初始化OLE/COM库环境在应用程序类的ExitInstance成员函数中添加释放程序占用COM资源的代码:::CoUninitialize();

2.导入ADO库文件

由于ADO类的定义是作为一种资源存储在ADODLL(msado15.dll〕中,在使用ADO之前,必须在工程stdafx.h文件的所有Include后面,导入ADO库文件,以便编译器能正确编译,代码如下:#import"C:\ProgramFiles\commonfiles\system\ado\msado15.dll"no_namespacerename("EOF","adoEOF")参数no_namespace说明ADO对象不使用命名空间,如何使用命名空间,那么参数为:rename_namespace("AdoNS")。参数rename是将ADO中的EOF〔文件结束〕更名为adoEOF,以免和自己的EOF冲突。

3.利用智能指针进行数据库操作

ADO库包含了三个智能指针:〔1〕_ConnectionPtr:用来创立一个数据连接或执行一条不返回任何结果的SQL语句。〔2〕_CommandPtr返回一个记录集,它提供了一种简单方法来执行返回记录集的存储过程或SQL语句。提示:在使用_CommandPtr接口时,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接字符串。〔3〕_RecordsetPtr是一个记录集对象,提供了对记录集的控制,如记录锁定、游标控制等。利用智能指针进行数据操作主要有以下几个步骤:①在视图类中添加三个智能指针的数据成员:_ConnectionPtr m_pConnection;_RecordsetPtr m_pRecordset;_CommandPtr m_pCommand;②在视图类的初始化更新函数中对三个智能指针进行初始化:m_pConnection.CreateInstance(_uuidof(Connection)); //初始化Connection指针m_pRecordset.CreateInstance(_uuidof(Recordset)); //初始化Recordset指针m_pCommand.CreateInstance(_uuidof(Command)); //初始化Command指针CreateInstance也提供相应的字符串版本来进行智能指针的初始化,如://m_pCommand.CreateInstance("ADODB.Command");③如果要连接Access数据库stuscore.mdb,那么可调用m_pConnection的Open函数:m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;DataSource=stuscore.mdb;〞,"","",0);3.利用智能指针进行数据库操作④下面的代码是得到一个记录集:CStringstrSql="select*fromstuinfo";BSTRbstrSQL=strSql.AllocSysString();m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText);⑤下面的代码是对数据集进行遍历:while(!m_pRecordset->adoEOF){//方法1:获取记录字段值_variant_tTheValue; //VARIANT数据类型//获取学生姓名TheValue=m_pRecordset->GetCollect("STUNAME"); /*//方法2:获取记录字段值_bstr_tTheValue1=m_pRecordset->Fields->GetItem("BIG_NAME")->Value;

温馨提示

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

评论

0/150

提交评论