清华版第14章数据库编程.ppt

上传人:za****8 文档编号:14274380 上传时间:2020-07-15 格式:PPT 页数:95 大小:894.56KB
返回 下载 相关 举报
清华版第14章数据库编程.ppt_第1页
第1页 / 共95页
清华版第14章数据库编程.ppt_第2页
第2页 / 共95页
清华版第14章数据库编程.ppt_第3页
第3页 / 共95页
点击查看更多>>
资源描述
第14章 数据库编程,14.1 ODBC的基本概念 14.2 MFC的ODBC类 14.3 创建一个ODBC数据源的数据库管理程序实例 14.4 深入理解CRecordset类,14.5 几个有用的函数 14.6 增加程序的功能 14.7 DAO简介 14.8 小结 习题,MFC提供了对数据库编程的强大支持。对于数据库的访问,MFC提供了两组类: ODBC(open database connectivity)和DAO(database access object)。利用这两个功能强大的类,用户可以方便地开发出基于ODBC或DAO的数据库应用。,ODBC(open database connectivity,开放数据库互连)是微软公司开放服务结构(windows open services architecture,WOSA)中有关数据库的一个组成部分,它建立了一组规范,并提供了一组对数据库访问的标准API(应用程序编程接口)。这些API利用SQL来完成其大部分任务。ODBC本身也提供了对SQL语言的支持,用户可以直接将SQL语句送给ODBC。,14.1 ODBC的基本概念,一个基于ODBC的应用程序对数据库的操作不依赖任何DBMS(database manager system, 数据库管理系统),不直接与DBMS打交道,所有的数据库操作由对应的DBMS的ODBC驱动程序完成。也就是说,不论是FoxPro、Access还是Oracle数据库,均可用ODBC API进行访问。由此可见,ODBC的最大优点是能以统一的方式处理所有的数据库。,ODBC管理器(administrator)位于Windows控制面板(control panel)的32位ODBC内,其主要任务是管理安装的ODBC驱动程序和管理数据源。 驱动程序管理器(driver manager)包含在ODBC32.DLL中,对用户是透明的。其任务是管理ODBC驱动程序,是ODBC中最重要的部件。 ODBC 驱动程序是一些DLL,提供了ODBC和数据库之间的接口。 数据源包含了数据库位置和数据库类型等信息,实际上是一种数据连接的抽象。,应用程序要访问一个数据库,首先必须用ODBC管理器注册一个数据源,管理器根据数据源提供的数据库位置、数据库类型及ODBC驱动程序等信息,建立起ODBC与具体数据库的联系。这样,只要应用程序将数据源名提供给ODBC,ODBC就能建立起与相应数据库的连接。 在ODBC中,ODBC API不能直接访问数据库,必须通过驱动程序管理器与数据库交换信息。驱动程序管理器负责将应用程序对ODBC API的调用传递给正确的驱动程序,而驱动程序在执行完相应的操作后,将结果通过驱动程序管理器返回给应用程序。在访问ODBC数据源时需要ODBC驱动程序的支持。,MFC的ODBC类对较复杂的ODBC API进行了封装,提供了简化的调用接口,从而大大方便了数据库应用程序的开发。程序员不必了解ODBC API和SQL的具体细节,利用ODBC类即可完成对数据库的大部分操作。,14.2 MFC的ODBC类,MFC的ODBC类主要包括: (1) CDatabase类, 主要功能是建立与数据源的连接。 (2) CRecordset类, 该类代表从数据源选择的一组记录(记录集),程序可以选择数据源中的某个表作为一个记录集,也可以通过对表的查询得到记录集,还可以合并同一数据源中多个表的列到一个记录集中。通过该类可对记录集中的记录进行滚动、修改、增加和删除等操作。,(3) CRecordView类, 提供了一个表单视图与某个记录集直接相连,利用对话框数据交换机制(DDX)在记录集与表单视图的控件之间传输数据。该类支持对记录的浏览和更新,在撤销时会自动关闭与之相联系的记录集。 (4) CFieldExchange类, 支持记录字段数据交换(DFX),即记录集字段数据成员与相应的数据库的表的字段之间的数据交换。该类的功能与CDataExchange类的对话框数据交换功能类似。 (5) CDBException类, 代表ODBC类产生的异常。,概括地讲,CDatabase针对某个数据库,它负责连接数据源; CRecordset针对数据源中的记录集,它负责对记录的操作; CRecordView负责界面,而CFieldExchange负责CRecordset与数据源的数据交换。 利用AppWizard和ClassWizard,用户可以方便地建立数据库应用程序,但这并不意味着可以对MFC的ODBC类一无所知。应注意阅读后面几小节中的内容,为学习后面的例子打好基础。,要建立与数据源的连接,首先应构造一个CDatabase对象,然后再调用CDatabase的Open成员函数。Open函数负责建立连接,其声明为: virtual BOOL Open( LPCTSTR lpszDSN, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR lpszConnect = ODBC;, BOOL bUseCursorLib = TRUE ); throw( CDBException, CMemoryException );,14.2.1 CDatabase类,参数lpszDSN指定了数据源名,在lpszConnect参数中也可包括数据源名,此时lpszDSN必须为NULL,若在函数中未提供数据源名且使lpszDSN为NULL,则会显示一个数据源对话框,用户可以在该对话框中选择一个数据源。参数bExclusive说明是否独占数据源,由于目前版本的类库还不支持独占方式,故该参数的值应该是FALSE,这说明数据源是被共享的。,参数bReadOnly若为TRUE则对数据源的连接是只读的。参数lpszConnect指定了一个连接字符串,连接字符串中可以包括数据源名、用户账号(ID)和口令等信息,字符串中的“ODBC”表示要连接到一个ODBC数据源上。参数bUseCursorLib若为TRUE,则会装载光标库,否则不装载,快照需要光标库,动态集不需要光标库。若连接成功,函数返回TRUE,若返回FALSE,则说明用户在数据源对话框中按了Cancel按钮。若函数内部出现错误,则框架会产生一个异常。,下面是一些调用Open函数的例子: CDatabase m_db; /在文档类中嵌入一个CDatabase对象 /连接到一个名为Student Registration的数据源 m_db.Open(Student Registration); /在连接数据源的同时指定了用户帐号和口令 m_db.Open(NULL,FALSE,FALSE,ODBC;DSN=Student Registration;UID=ZYF;PWD=1234); m_db.Open(NULL); /将弹出一个数据源对话框,要从一个数据源中脱离,可调用函数Close。在脱离后,可以再次调用Open函数来建立一个新的连接。调用IsOpen可判断当前是否有一个连接,调用GetConnect可返回当前的连接字符串。函数的声明为: virtual void Close( ); BOOL IsOpen( ) const; /返回TRUE则表明当前有一个连接 const CString CDatabase的析构函数会调用Close,所以只要删除了CDatabase对象就可以与数据源脱离。,CRecordView(记录视图)是CFormView的派生类,它提供了一个表单视图来显示当前记录,用户可以通过表单视图显示当前记录。通过记录视图,可以修改、添加和删除数据,用户一般需要创建一个CRecordView的派生类,并在其对应的对话框模板中加入控件。,14.2.2 CRecordView类,记录视图使用DDX数据交换机制在表单中的控件和记录集之间交换数据。在前面介绍的DDX都是在控件和控件父窗口的数据成员之间交换数据,而记录视图则是在控件和一个外部对象(CRecordset的派生类对象)之间交换数据。清单显示了一个CRecordView的派生类的DoDataExchange函数,可以看出,该函数是与m_pSet指针指向的记录集对象的域数据成员交换数据的。而且,交换数据的代码是ClassWizard自动生成的。在后面的例子中,将介绍用ClassWizard连接记录视图与记录集对象的方法。,在函数的开头先调用CRecordset:Edit进入编辑模式,接着调用UpdateData将控件中的数据更新到记录集对象的域数据成员中,然后调用CRecordset:Update将域数据成员的值写入数据源,这说明OnMove在滚动记录的同时会完成对原来记录的修改。 在函数的中间有一个分支语句用来处理4个不同的命令,在这个分支语句中调用了CRecordset的各种用于滚动记录的成员函数,这些函数在滚动到一个新的记录时会把该记录的内容设置到域数据成员中。在函数的末尾调用UpdateData(FALSE)把新的当前记录的内容设置到表单的控件中。,由此可见,OnMove一来一回完成了两次表单控件和数据源的数据交换过程。通过分析该函数,可以学会在浏览记录时如何控制DDX和DFX数据交换。,例14.1 创建一个学生信息管理的数据库应用程序。 使用ODBC数据源,因此首先应该创建数据库,这里采用Access 来创建,创建的步骤如下: (1) 运行Access,建立一个新数据库,建立方法可以参考有关书籍。,14.3 创建一个ODBC数据源的数据库管理程序实例,(2) 数据库创建完毕,就可以来创建ODBC数据源了,单击计算机的“开始”按钮,选择“设置”“控制面板”命令,在弹出的控制面板对话框中,双击ODBC数据源图标,如图14.1所示。,图14.1 在控制面板上创建ODBC数据源,此时,弹出图14.2所示的对话框。,图14.2 创建ODBC数据源,单击“用户DSN”选项卡中的“添加”按钮,来创建一个Access类型的数据源,按照图14.3所示对话框进行设置,选取上面建好的数据库,正如所看到的,将数据源的名称取为“DSNSTUDENT”,这个名称在下面进行程序设计时要用到。,图14.3 设置数据源的名称,(3) 做完这些准备工作后,创建应用程序的框架。遵循以下步骤: 运行AppWizard来创建一个MFC AppWizard的新项目,将其命名为“student”。 第一步,选择基于Single document,语言支持中文。 第二步,选择Database view with file support,并单击Data Source按钮,为程序指定图14.4所示的数据源,集合类型选为Dynaset,单击OK按钮,在弹出的对话框中为程序选中可用的表“学生”(在本例中,它是惟一可用的表),单击OK按钮,完成后单击Next按钮。,图14.4 在创建应用程序框架时指定数据源,第三步到第六步,保持默认设置,完成应用程序的框架设计。 这时,可先停下来,认真看一下应用程序向导所做的一切。生成的类中有两点与以前的不一样,一是类CStudentView,它由CRecordView类派生,而CRecordView类是CFormView的子类,它在CFormView类的基础上添加了支持数据库的功能,前面对它已有阐述; 二是CStudentSet类,它由CRecordSet类派生而来,关于CRecordSet类在前面已作过介绍。,(4) 进行窗体设计。在项目区中选择类视图区展开Dialog,双击IDD_STUDENT_FORM编辑显示的窗体,按图14.5添加控件, 然后按表14.1来设置控件的属性。(见书上表14.1),图14.5 设计显示数据库数据的表单,将控件与变量进行关联,步骤如下: 运行类向导,在Member Variables选项卡中,选择相应的控件后单击Add Variable按钮。所需关联的变量见表14.2。(见书上表14.2),程序中应出现以下的代码: void CStudentView:DoDataExchange(CDataExchange* pDX) CRecordView:DoDataExchange(pDX); /AFX_DATA_MAP(CStudentView) / NOTE: the ClassWizard will add DDX and DDV calls here /AFX_DATA_MAP DDX_FieldText(pDX,IDC_EID,m_pSet-m_ID,m_pSet); DDX_FieldText(pDX,IDC_ENAME,m_pSet-m_name,m_pSet); DDX_FieldText(pDX,IDC_EZIP,m_pSet-m_zip,m_pSet);,DDX_FieldText(pDX,IDC_ETELEPHONE,m_pSet-m_telephone,m_pSet); DDX_FieldText(pDX,IDC_ECITY,m_pSet-m_city,m_pSet); DDX_FieldText(pDX,IDC_EPROVINCE,m_pSet-m_province,m_pSet); DDX_FieldText(pDX,IDC_EADDRESS,m_pSet-m_address,m_pSet); DDX_FieldText(pDX,IDC_EMAJOR,m_pSet-m_major,m_pSet); ,上面的代码体现了视图中控件与变量的数据交换的机制。 此时调试运行程序,如果顺利的话,应该看到图14.6所示的运行界面。在界面上,它与一般的单文档应用程序显著的不同是在工具栏上多了一组数据库程序特有的按钮,它们实现在数据库记录间的移动; 在菜单条中,也会多出“记录”菜单项,打开这个菜单可以看到有4个子菜单,“第一个记录”、“前一个记录”、“下一个记录”和“最后一个记录”,它们分别对应着前面所说的工具栏中4个按钮。,图14.6 程序的运行结果,此时,除了浏览记录外,还可以修改记录的内容。这里值得注意的是,尽管在程序中已修改了记录的内容,但数据库没有立即更新,直到用户移动了当前记录,才能实现数据库的更新。,CRecordset类代表一个记录集,该类是MFC的ODBC类中最重要、功能最强大的类之一。 记录集主要分为快照(Snapshot) 和动态集(Dynaset)两种,CRecordset类对这两者都支持。这两种记录集的不同,表现在它们对别的应用改变数据源记录采取了不同的处理方法。,14.4 深入理解CRecordset类,快照型记录集提供了对数据的静态视图。快照是个很形象的术语,就好像对数据源的某些记录拍了一张照片一样。当别的用户改变了记录时(包括修改、添加和删除),快照中的记录不受影响。需要指出的是,快照的这种静态特性是相对于别的用户而言的,它会正确反映由本身用户对记录的修改和删除,但对于新添加的记录直到调用Requery后才能反映到快照中。,动态集提供了数据的动态视图,当别的用户修改或删除了记录集中的记录时,会在动态集中反映出来。当滚动到修改过的记录时,对其所作的修改会立即反映到动态集中,当记录被删除时,MFC代码会跳过记录集中的删除部分,对于其他用户添加的记录,直到调用Requery时,才会在动态集中反映出来。本身应用程序对记录的修改、添加和删除会反映在动态集中。当数据是动态的时候,使用动态集是最适合的。,快照和动态集有一个共同的特点,那就是在建立记录集后,记录集中的成员就已经确定了,这就是为什么两种记录集都不能反映别的用户添加记录的原因。,本例中建立的是动态集类型的记录集。见下面的代码: CStudentSet:CStudentSet(CDatabase* pdb) : CRecordset(pdb) /AFX_FIELD_INIT(CStudentSet) m_ID = 0; m_name = _T(); m_address = _T(); m_city = _T(); m_province = _T(); m_zip = _T(); m_telephone = _T(); m_major = _T();,m_numstu = 0; m_nFields = 9; /AFX_FIELD_INIT m_nDefaultType = dynaset; /记录集的类型为动态 CString CStudentSet:GetDefaultConnect() return _T(ODBC;DSN=DSNSTUDENT); /设置数据源 CString CStudentSet:GetDefaultSQL() return _T(学生); /设置管理的数据表 ,CRecordset类代表一个记录集,用户一般需要用ClassWizard创建一个CRecordset的派生类。ClassWizard可以为派生的记录集类创建一批数据成员,这些数据成员与记录的各字段相对应,被称为字段数据成员或域数据成员。域数据成员用来保存某条记录的各个字段,它们是程序与记录之间的缓冲区。域数据成员代表当前记录,当在记录集中滚动到某一记录时,框架自动地把记录的各个字段拷贝到记录集对象的域数据成员中,当用户要修改当前记录或增加新记录时,程序先将各字段的新值放入域数据成员中,然后调用相应的CRecordset成员函数把域数据成员设置到数据源中。,因此,在记录集与数据源之间有一个数据交换问题。CRecordset类使用“记录域交换”( Record Field Exchange,缩写为RFX)机制自动地在域数据成员和数据源之间交换数据。RFX机制与对话数据交换(DDX)类似,CRecordset的成员函数DoFieldExchange负责数据交换任务,在该函数中调用了一系列RFX函数,一般由ClassWizard自动建立。下面是本例中为数据交换建立的代码: void CStudentSet:DoFieldExchange(CFieldExchange* pFX) ,/AFX_FIELD_MAP(CStudentSet) pFX-SetFieldType(CFieldExchange:outputColumn); RFX_Long(pFX, _T(ID), m_ID); RFX_Text(pFX, _T(name), m_name); RFX_Text(pFX, _T(address), m_address); RFX_Text(pFX, _T(city), m_city); RFX_Text(pFX, _T(province), m_province); RFX_Text(pFX, _T(zip), m_zip); RFX_Text(pFX, _T(telephone), m_telephone); RFX_Text(pFX, _T(major), m_major); RFX_Long(pFX, _T(numstu), m_numstu); /AFX_FIELD_MAP ,CRecordset提供了几个成员函数用来在记录集中滚动,当用这些函数滚动到一个新记录时,框架会自动地把新记录的内容拷贝到域数据成员中。 void MoveNext() 前进一个记录; void MovePrev() 后退一个记录; void MoveFirst() 滚动到记录集中的第一个记录; void MoveLast() 滚动到记录集中的最后一个记录; void SetAbsolutePosition( long nRows ),该函数用于滚动到由参数nRows指定的绝对位置处;,14.5 几个有用的函数,BOOL IsEOF() const如果记录集为空或滚动过了最后一个记录,那么函数返回TRUE,否则返回FALSE; BOOL IsBOF() const 如果记录集为空或滚动过了第一个记录,那么函数返回TRUE,否则返回FALSE。,上面的程序总还缺少点什么。下面,为程序添加两个功能,记录的添加和记录的删除。实现这两个功能,有必要接着上文讲一下记录添加和删除的实现。,14.6 增加程序的功能,要向记录集中添加新的记录,应该按下列步骤进行: (1) 调用AddNew成员函数进入添加模式,该函数把所有的域数据成员都设置成NULL(注意,在数据库术语中,NULL是指没有值,这与C+的NULL是不同的)。与Edit一样,AddNew会把当前域数据成员的内容保存在一个缓冲区中,在必要的时候,程序可以再次调用AddNew取消添加操作并恢复域数据成员原来的值,调用后程序仍处于添加模式,调用Move(AFX_MOVE_REFRESH)可退出添加模式,同时该函数会从缓冲区中恢复域数据成员。,(2) 调用Update把域数据成员中的内容作为新记录写入数据源,从而结束添加。 如果记录集是快照,那么在添加一个新的记录后,需要调用Requery重新查询,因为快照无法反映添加操作。,要删除记录集的当前记录,应按下面两步进行: (1) 调用Delete成员函数,该函数会同时给记录集和数据源中当前记录加上删除标记。注意不要在一个空记录集中调用Delete,否则会产生一个异常。 (2) 滚动到另一个记录上以跳过删除记录。,上面提到的函数声明为: virtual void AddNew( );throw( CDBException ); virtual void Delete( );throw( CDBException ); virtual BOOL Update( );throw( CDBException ); 若更新失败则函数返回FALSE,且会产生一个异常。,在对记录集进行更改以前,程序也许要调用下列函数来判断记录集是否可以更改,因为如果在不能更改的记录集中进行修改、添加或删除将导致异常的产生。 BOOL CanUpdate( ) const; /返回TRUE表明记录是可以修改、添加和删除的。 BOOL CanAppend( ) const; /返回TRUE则表明可以添加记录。,本例中,在进行记录的添加时,有一个需要注意的问题,因为在数据表的设计时将编号作为记录的主关键字,这要求在添加记录时,每两个记录的编号项不能相同。可以通过设置编号所对应的文本框的属性来解决这个问题,冻结文本框的可编辑功能,使之只用于显示,编号由程序自动添加。在窗体设计的环境下右击编号所对应的文本框,在弹出的属性框中核选Disabled选项。,添加和删除功能采用菜单驱动,为此需要编辑菜单资源,方法与以前相同。增加两个菜单和一个分隔栏,如图14.7所示,菜单属性设计见表14.3。,图14.7 设计菜单,表14.3 设置菜单的属性,为菜单映射函数,方法在前文已有阐述。编辑下面的代码: void CStudentView:OnAdd() / TODO: Add your command handler code here CRecordset * pset = OnGetRecordset(); /保存当前记录的任何变化 if (pset-CanUpdate() ,/获取新记录的ID号 long m_lnewID=m_pSet-GetMaxID()+1; /添加新记录 m_pSet-AddNew(); m_pSet-m_ID=m_lnewID; /保存新记录 m_pSet-Update(); /更新记录集 m_pSet-Requery(); m_pSet-MoveLast(); /更新显示窗体 UpdateData(FALSE); ,void CStudentView:OnDelrec() / TODO: Add your command handler code here if (MessageBox(Are you sure you want to delete this record?, Delete this record?,MB_YESNOCANCEL | MB_ICONQUESTION)=IDYES), /删除当前记录 m_pSet-Delete(); /数据记录指针前移 m_pSet-MovePrev(); /更新数据 UpdateData(FALSE); ,除了ODBC 类,MFC也提供了一组DAO(database access object)类,也可以用来创建数据库应用程序。DAO在很大程度上是ODBC 类的超集,它包含了ODBC 类的大部分功能。与ODBC一样,DAO提供了一组API供编程使用,从而大大简化了程序的开发。利用MFC的DAO类,用户可以编写独立于DBMS的应用程序。,14.7 DAO简介,DAO类与ODBC类相比具有很多相似之处。首先,二者都支持对各种ODBC数据源的访问。虽然二者使用的数据引擎不同,但都可以满足用户编写独立于DBMS的应用程序的要求; 其次,DAO提供了与ODBC功能相似的MFC类,它们的大部分成员函数都是相同的。,由于DAO类使用了微软Jet数据库引擎,与ODBC类十分相似,因此只要掌握了ODBC,就很容易学会使用DAO。实际上,可以很轻松地把数据库应用程序从ODBC移植到DAO,只需要将程序中使用的类的名字对应到DAO中。即CDatabase 改为CDaoDatabase, CRecordset 改为CDaoRecordset, CRecordView 改为CDaoRecordView。,在ODBC 和DAO之间还有许多不同的地方。其中,一个较大的不同是系统实现函数的方法不同,ODBC 使用一组DLL实现,而DAO使用OLE对象来实现。 一般地讲,DAO类提供了比ODBC类更广泛的支持。一方面,只要有ODBC驱动程序,使用Microsoft Jet的DAO就可以访问ODBC数据源。另一方面,由于DAO是基于Microsoft Jet引擎的,因而在访问Access数据库(即*.MDB文件)时具有很好的性能,但在访问其他类型的库时,效率不是很高。,还有以下的不同之处: (1) 记录集的默认类型不同。ODBC记录集的默认类型是快照(Snapshot),而DAO默认类型则是动态集(Dynaset)。 (2) 参数化的方式不同。DAO记录集的m_strFilter和m_strSort中的参数不是“?”号,而是一个有意义的参数名。,例如,在下面的过滤器中有一个名为CourseIDParam的参数: m_pSet-m_strFilter =CourseID = CourseIDParam; 在DoFieldExchange函数中,有下面两行: pFX-SetFieldType(CDaoFieldExchange:param); DFX_Text(pFX, _T(CourseIDParam), m_strCourseIDParam); DFX函数的第二个参数也是CourseIDParam。,(3) 处理异常的方式不同。例如,在删除记录时,对异常的处理如下所示: try m_pSet-Delete(); catch(CDaoException* e) AfxMessageBox(e- m_pErrorInfo-m_strDescription); e-Delete(); ,DAO记录集是使用是DFX数据交换机制(DAO record field exchange)而不是RFX,在DAO记录集的DoFieldExchange中, 使用的是DFX函数而不是RFX函数。,DAO可以通过ODBC驱动程序访问ODBC数据源。但DAO是基于Microsoft Jet引擎的,通过该引擎,DAO可以直接访问Access、FoxPro、dBASE、Paradox、Excel和Lotus WK等数据库。CDaoDatabase类可以直接与这些数据库进行连接,而不必在ODBC管理器中注册DSN。例如,下面的代码用来打开一个FoxPro数据库: CDaoDatabase daoDb; daoDb.Open( “”,FALSE,FALSE,FoxPro 2.5;DATABASE=c:zyf);,CDaoDatabase:Open函数用来连接某个数据库,该函数的声明为: virtual void Open( LPCTSTR lpszName, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR lpszConnect = _T() ); throw( CDaoException, CMemoryException );,参数bExclusive如果为TRUE,则函数以独占方式打开数据库,否则就用共享方式。如果bReadOnly为TRUE,那么就以只读方式打开数据库。如果要打开一个Access数据库,则可以在lpszName参数中指定MDB文件名。如果要访问非Access数据库,则应使该参数为“”,并在lpszConnect中说明一个连接字符串。连接字符串的形式一般为“数据库类型; DATABASE=路径(文件)”,例如“dBASE ;DATABASE=c:MYDIR”。,Open函数也可以打开一个ODBC数据源,但这需要相应的ODBC驱动程序,并需要在ODBC管理器中注册DSN。此时lpszConnect的形式为“ODBC;DSN=MyDataSource”。显然,用DAO访问象FoxPro这样的数据库时,直接打开比把它当作ODBC数据源打开要省事。,支持DDL是DAO对数据库编程良好支持的一个重要体现。DDL(data definition language)在SQL术语中叫做“数据定义语言”,它用来完成生成、修改和删除数据库结构的操作。ODBC类只支持DML(data manipulation language,数据操作语言),不支持DDL,所以用ODBC类只能完成数据的操作,不能涉及数据库的结构。要执行DDL操作,只有通过ODBC API。而DAO类同时提供了对DML和DDL的支持,这意味着程序可以使用DAO类方便地创建数据库及修改数据库的结构。,与ODBC相比,DAO提供了一些新类来加强其功能,这些新类包括: CDaoTableDef类提供了对表的结构的定义。调用CDaoTableDef:Open可以获得表的结构定义, 调用CDaoTableDef:Create可以创建一张新表,调用CDaoTableDef: CreateField可为表添加字段,调用CDaoTableDef:CreateIndex可以为表添加索引, 调用CDaoTableDef:Append可以把新创建的表保存到数据库中。,CDaoQueryDef类代表一个查询定义(Query definition),该定义可以被存储到数据库中。 CDaoWorkspace提供了数据工作区(Workspace)。一个工作区可以包含几个数据库,工作区可以对所属的数据库进行全体或单独的事务处理,工作区也负责数据库的安全性。如果需要,程序可以打开多个工作区。,DAO的另一个重要特色在于它对Access数据库提供了强大的支持。由于DAO是基于Microsoft Jet引擎的,所以DAO肯定要在Access数据库上多做一些文章。例如,调用CDaoDatabase:Create可以直接建立一个MDB文件,代码如下所示: m_db.Create(d:zdmstudent.mdb); 利用AppWizard和ClassWizard,用户可以方便地开发出性能优良的基于DAO的Access数据库应用程序。,由于DAO可以访问ODBC数据源,下面几条可以作为DAO替代ODBC的理由: 在某些情况下可以获得更好的性能,特别是在访问Microsoft Jet(.MDB)数据库时与ODBC兼容; DAO允许数据有效检查; DAO允许用户说明表与表之间的关系。,当然,DAO的出现并不意味着ODBC已经过时了。如果用户的工作必须严格限于ODBC数据源,尤其是在开发Client/Server结构的应用程序时,用ODBC有较好的性能。,例14.2 用DAO技术来改写例14.1中以ODBC为数据源的应用实例。 按照与前面类似的步骤来创建DAO数据源的应用程序,只是在指定数据源时,指定一个DAO数据源,如图14.8所示,只要在对话框中选中DAO单选按钮,并指定相应的数据库文件的目录路径。并将新项目的名称设为daostu。此时,应用程序向导能够创建如图14.9所示的几个类。在此,可以比较与例14.1的不同之处,以了解两类数据源的不同。,图14.8 为工程指定DAO数据源,图14.9 应用程序向导为新工程创建的类,在对新工程进行功能设置时,为了提高效率,避免再次输入例14.1中的代码及再次进行视图的设计,可以向新工程的工作区添加原先的实例工程,直接拷贝页面布局及相应的代码。具体做法如下: 选择菜单命令ProjectInsert Project into Workspace,弹出一对话框,在该对话框中选择相应的工程文件d:exof6studentstudent.dsp,如图14.10所示。添加另一工程后的工程区窗口如图14.11所示。,图14.10 向新工程所在工作区间 添加前一个实例工程,图14.11 添加了另一工程后的视图区,首先,在视图内工程student对应的资源视图目录下找到对话框条目,将IDD_STUDENT_FORM对应的窗口布局复制到新工程的视图IDD_DAOSTU_FORM中。 接下来,复制菜单资源中用于添加和删除记录的两个菜单项, 并分别为它们添加相应的响应处理函数。 最后,复制相应的处理函数代码。表14.4显示相应函数的对应项。,表14.4 两个工程中对应函数,接着,还应为添加的控件指定关联变量。可以利用类向导来完成这个任务,按照表14.2所示,分别为各个控件指定关联变量,如图14.12所示。 编译新工程,可以看到,它能够完成例14.1的功能。,图14.12 指定控件关联变量,本章重点介绍了如下内容: ODBC基本概念; MFC的ODBC类简介; CDatabase类、CRecordset类、CRecordView类功能概述; MFC的DAO和DAO类简介。 借助AppWizard和ClassWizard工具创建了一个数据库应用例程,分别以ODBC数据源和DAO数据源来实现。,14.8 小结,14-1 ODBC的含义是什么? 14-2 MFC中与ODBC有关的类有哪些?各有什么功能? 14-3 利用熟悉的数据库管理系统建立一个数据库,并建立关于该数据库的数据源。 14-4 如何使用ClassWizard类向导建立一个数据库应用程序? 14-5 ODBC类和DAO类在系统实现上有哪些不同之处?,习题,14-6 利用ODBC编写一个有关学生成绩数据库.dbf的应用程序,其主要任务是: (1) 在屏幕上显示学生的成绩; (2) 学生的英语成绩在90分以上,语言能力成绩在60分以下时,其语言能力成绩加10分; (3) 为学生成绩数据库添加10个新记录,并以数学成绩为索引对记录进行排序; (4) 删除学生成绩数据库中语文成绩小于50的记录; (5) 画一个饼图,显示学生平均成绩在0分59分、60分79分、80分89分及90分以上的百分比例。,14-7 利用DAO技术改写上一题的代码,实现同样的功能。,
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!