当前位置:首页 > 芯闻号 > 充电吧
[导读]                                                         目录概述 2开始编写一个数据库应用程序: 2建立一个数据库应用程序 2对数据库的操作:

                                                         目录

概述 2

开始编写一个数据库应用程序: 2

建立一个数据库应用程序 2

对数据库的操作: 3

1.打开数据库: 3

2.查询: 3

3.更新数据库: 4

4.添加数据: 4

5.删除: 5

6.排序: 5

CDaoDatabase class 和CdaoRecordset class 6

插入Crecordset派生类: 8



课程设计要求


概述

ODBC和ADO

MFC中对数据库的链接方法主要有两种:DOBC和ADO。

ODBC是微软公司提供的一组数据库访问方式,包含一系列的对数据库进行操作的API函数。一个ODBC应用程序对数据库的操作并不依赖于任何的DBMS,而是由对应的DBMS的ODBC驱动来完成。这些驱动有些在安装数据库或者操作系统或者编译软件的时候就已经装上了,所以我们并不需要考虑驱动安装的问题。而由于ODBC对数据库的访问操作时通过驱动来完成的,所以不管是什么类型的数据库,我们只要在数据源中指定了相应的驱动就可以在应用程序中使用ODBC来访问。

一个完整的ODBC程序包括:应用程序,ODBC管理器,驱动程序管理器,ODBC API,驱动程序和数据源,我们在编写一个ODBC应用程序的时候,就是一个注册数据源,编写程序对数据源的数据库进行访问的过程。

更多信息请查阅相关资料。

ADO。面向对象的数据库访问技术,基于OLE DB,是一种高层的访问技术,速度快,易于使用。在MFC中,ADO的许多使用方法类似于ODBC。


开始编写一个数据库应用程序:

前面说了一些必要的废话,只是为了象征性的说明我们在应用一门技术的时候要掌握其基本原理和特征。下面开始将怎么在XP + SQL Server2000 + VC++6.0环境中编写一个基于ODBC的数据库程序,ADO在使用中和ODBC有许多的相似之处,了解了ODBC后再去学习ADO会是一件很轻松的事情。


要写一个数据库系统,首先要做的是注册数据源,控制面板管理工具中有数据源。众所周知的事情就不说了。



建立一个数据库应用程序。

众所周知,在使用VC6编写MFC应用程序的时候先要建立工程。我们手头的参考书中有说明如何建立一个ODBC的数据库应用程序,不再浪费文字过多描述。书上的这个工程是一个单文档应用程序(貌似只中当文档应用程序在新建的时候可以添加数据源)。工程建立完成后在CobjNameView(objName为工程名)类中会自动定义了一个“m_pSet”成员变量,这个变量的类型是CobjNameSet(objName为工程名),其父类为CRecordset,拿这个类出来说事是因为这个类负责了应用程序和数据库相关的操作,打开这个类,我们可以看见其中定义了成员变量为public,仔细观察就会发现这几个变量的名称,类型和数据源表中的属性一一对应了。再看这个成员函数:DoFieldExchange()。和DoDataExchange()函数的功能很类似,不过一个是将变量(CobjNameSet类的几个数据成员)和数据库中某个元组的属性值关联,而另一个是将视图中的控件和某个变量项关联(是我们为控件添加变量的效果)。这应该ODBC的数据交换机制(我想不出更好的词汇来形容它,手头可查资料太少),这种实现机制的使用使得我们可以只需要考虑程序中的变量值而不需要去管数据库中的属性名是什么。


对数据库的操作:

1.打开数据库:

MFC中对CRecordset::Open()函数的定义如下:


virtual BOOL Open( 

   UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE, 

   LPCTSTR lpszSQL = NULL, 

   DWORD dwOptions = none  

);


nOpenType打开方式,包括以下方式:

CRecordset::dynaset

CRecordset::snapshot

CRecordset::dynamic

CRecordset::forwardOnly


lpszSQL,打开数据库的SQL语句。

dwOptions,操作方式,比如说是否是只读(CRecordset::readOnly)。


当然,当我们使用MFC自动创建数据库连接的CRcordSet派生类的时候,并不需要我们显式的调用这个函数。VC中创建MFC ODBC应用程序的时候貌似也没有调用这个函数,不过事实是这样的,你的数据库在程序中刚开始就处于打开状态了,具体是怎么实现的我也不是很清楚,大概和这个类里面定义的GetDefaultConnect()成员函数和GetDefaultSQL()函数有关。



2.查询:

要点:m_strFilter变量

CString m_strFilter;

这个变量的作用体现在查找的时候。变量的值取SQL的Select语句的WHERE关键字后面的部分,比如查找姓名为张三的学生:

Example:

m_pSet->m_ strFilter = _T(“sname=’张三’”);

m_pSet->Close();

m_pSet->Open();

while(m_pSet->IsEOF()){

*/

出查询结果

/

_pSet->MoveNext();

}

m_pSet->m_ strFilter = _T(“”);//这句很重要


从例子里可以猜测出,m_ strFilter被赋予打开条件的字符串值之后,数据库被关闭再打开(事实上这个变量的作用只体现在打开的时候,因为程序中的数据库在一开始就是处于打开状态,所以才要先关闭数据库再打开,如果你不确定,可以使用CRcordSet:: IsOpen()函数进行判断),得到的元组集合(不知道怎么描述比较准确)就是符合m_ strFilter 条件的子表(感觉有点像是视图),我们可以对子表中的元组进行遍历等操作。记得用完之后清空这个变量的值,要不你下次操作数据库的时候就看可能会遇见麻烦了。

这里还用到了另外两个函数:

void Close( ); BOOL IsEOF( ) const;

功能显然易见,不多少。

另外补充几个函数:

CRcordSet:: IsBOF();是否到顶

CRcordSet:: IsOpen();是否打开

CRcordSet ::MoveFirst();移动到第一条记录

CRcordSet ::MoveLast();移动到最后一条记录


3.更新数据库:

easy了,ODBC中更新数据库是一件很轻松的事情,只要调用CRcordSet::Edit() 函数就OK了,看个简单的例子,出自MSDN:

Example:

// To edit a record, first set up the edit buffer

rsCustSet.Edit();

// Then edit field data members for the record

rsCustSet.m_BillingID = 2795;

rsCustSet.m_ContactFirstName = _T("Jones Mfg");

// Finally, complete the operation

if(!rsCustSet.Update())

{

    // Handle the failure to update

    AfxMessageBox(_T("Couldn't update record!"));

}

可以看见,更新数据库具有固定的“套用模式”,首先调用CRcordSet::Edit() 函数,如例子中所说,设置更新缓存,然后对对应变量的值进行修改,完成后调用CRcordSet::Update() 函数,完成更新,这时候程序会自动将修改的结果写入数据库而不用你操心。当然,在更新数据库之前,你需要查找到你需要更新的元组(也称为记录),使用上面的查询方法。

4.添加数据:

函数:virtual void AddNew( );

一个简单的例子,说明一切问题:

Example:

m_pSet->AddNew();

m_pSet->m_TestName  = “TestName1”;

m_pSet->m_TestCode = “TestCode1”;

m_pSet->m_TestOthers = “Other Codes”;

m_pSet->Update();

如你所见,代码又一次很荣幸的被“夹在”了AddNew()和Update()之间。类似更新,首先告诉系统我要添加数据了(AddNew()),系统很无赖的给了你一块内存空间,让你可以对新的记录属性进行赋值,完了之后你又要告诉系统你已经搞定了,系统就不得不屁颠屁颠的去给你把数据写进数据库中(当然这之前会检测数据是否符合数据库的完整性约束)(Update())。添加操作到此完成。

5.删除:

这个不带劲,没什么好说的,delete谁都认识。

virtual void Delete( );

Example:

// Create a derived CRecordset object

CCustomer rsCustSet(&m_dbCust);

rsCustSet.Open();

if(rsCustSet.IsEOF() || !rsCustSet.CanUpdate() ||

   !rsCustSet.CanTransact())

{

   return;

}

m_dbCust.BeginTrans();

// Perhaps scroll to a new record...

// Delete the current record

rsCustSet.Delete();

// Finished commands for this transaction

if(IDYES == AfxMessageBox(_T("Commit transaction?"), MB_YESNO))

   m_dbCust.CommitTrans();

else // User changed mind

   m_dbCust.Rollback();

写的这么工整,肯定是出自MSDN了,这个家伙写的逻辑性很好。看见许多新鲜的东西吧,别问我,我懒得说,自己想去。额,你要看见的也就是从最后一行数起的第七行而已。


打开,关闭,更新,添加,删除,貌似我都说过了。排序么,其实你不用在数据库中完成了。

6.排序:

方法一:去程序里编写排序代码。

方法二:m_strSort。

那个已经快被遗忘的SQL语句:ORDER BY。聪明的孩子,想到了m_strFilter了没?没错,m_strSort 变量的取值就是SQL语句ORDER BY 后面的内容了,废话少说,看例子:

Example:

CCustomer rsCustSet(&m_dbCust);

// Set the sort string

rsCustSet.m_strSort = _T("L_Name, ContactFirstName");

// Run the sorted query

rsCustSet.Open(CRecordset::snapshot, _T("Customer"));

出自MSDN。额外说明,如果属性名(例子中是L_Name)包含空格的话,要用方括号括起来:rsCustSet.m_strSort = _T("[L Name], ContactFirstName");

Got it?

程序中表名,数据库名亦然。


说了这么多其实都是VC帮我们建好了关联数据库的类,貌似我们在创建工程的时候只有在单文档工程中才能添加数据源,貌似也只是一个数据源,一个类。万一我们要在一个对话框中使用数据库(例如登陆对话框),万一我们想添加多个数据源,多个Crecordset 类的派生类,多个关联数据库的视图(CrecordView 派生类)……




CDaoDatabase class 和CdaoRecordset class

出于个人习惯,这里说“手动”连接数据库使用这两个类,当然你也可以使用CDatabase class和CRecordset class,用法差不多。


以写一个登陆对话框为例。这里假定登陆对话框上有两个输入框,变量分别为m_username,m_password。登陆确定按钮IDOK;单选按钮:IDC_RADIO1,IDC_RADIO2;分别表示普通用户和管理员,为了节省时间,下面是本人的登录对话框IDOK按钮消息映射函数,仅供参考:

首先在文件顶部包含头文件:#include 

void CLoginDlg::OnOK() 

{

UpdateData(TRUE);

 

CDaoDatabase cdb;

CDaoRecordset *m_pSet;

COleVariant cv;

//CString nullchar="                    ";

/*调用CdaoDatabase::Open(),打开一个数据源(连接到一个数据库),并且分配相应的内存空间。第一个参数为数据源名称,第二个参数为是否是独占模式打开,第三参数为是否已只读模式打开,最后一个参数,额,缺少必要资料,不是很清楚,MSDN中也只是说A string expression used for opening the database。

 */

cdb.Open("Student_Score",FALSE,TRUE,"ODBC=;");

 /*

 初始化m_pSet变量,当然,这个必须要使用CDaoDatabase的对象来初始化,没什么好说的,函数调用而已。

 */

m_pSet = new CDaoRecordset(&cdb);

CString Sqlstr;

if(GetCheckedRadioButton(IDC_RADIO1,IDC_RADIO2)==IDC_RADIO1)

{

/*

如果登录用户选择的为学生

*/

 /*

 这老长的一串其实只是在写打开的SQL语句而而已,有一个好用的Open()函数可以用,我们就不用神经质一样的打开数据库再去查找了,easy的方法,写一个SQL的select语句,查询条件为用户名和密码,显然用户名是唯一的。用这个SQL语句做为Open()的第二个参数打开数据库。

*/

Sqlstr = "select StudentID,password from Student Where StudentID='" + m_UID + "' AND password='" + m_UPW + "'";

 /*

 “正式的调用CdaoRecordset::Open()” 函数,第一个参数表示打开方式,动态打开,第二个参数为打开数据库的SQL语句,Open()函数在打开数据库时会自动按照这个字符串的条件筛选数据库的所有元组,并且返回符合条件的元组集合(记录集),这个字符串的功能和m_strFilter相似,最后一个参数:nOptions,懒得说,0,NULL,随便你选。

*/

m_pSet->Open(dbOpenDynaset,Sqlstr,NULL);

if(!m_pSet->IsEOF()){//用户名密码正确

     /*判断依据?如果表中有符合条件的元组(用户名密码正确),Open()函数必然返回一个非空的元组集合,这时候当然不可能就到了表的结尾了*/

isAdmin = false;

m_pSet->Close();

cdb.Close();

CDialog::OnOK();

}

else

MessageBox("用户名或密码错误,n请重新输入。","错误");

}

else{

Sqlstr = "select AdminName,Password from Admin where AdminName='" + m_UID + "' AND Password='" + m_UPW + "'";

m_pSet->Open(dbOpenDynaset,Sqlstr,NULL);

if(!m_pSet->IsEOF()){

//MessageBox("管理员登陆之后的界面");

isAdmin = true;

m_pSet->Close();

cdb.Close();

CDialog::OnOK();

}

else

MessageBox("用户名或密码错误,n请重新输入。","错误");

}

}



插入Crecordset派生类:

VC6.0  MFC工程中:

1. 选择菜单栏InsertàNew Class…

2. Base class选择CRecordset,编辑好类名,如图所示,单击“OK”,弹出“Database Options”对话框。


3. 选择好数据源:如图。单击“OK”。弹出“Select Database Tables”对话框,选择数据库表。


4. 如图所示,选择一个数据库的表,建议一次只选择一个表,操作起来方便一些。单击“OK”。


5. 好,现在你创建的类已经添加到工程中了,可以在ClassView中看见他了。现在要说的就是如何使用它了。首先要在要包含这个类的头文件例如TestInsetClass.h;

定义类的对象:CtestInsetClass *m_pTestSet;

打开数据库:m_pTestSet->Open();

后面的操作和最前面所说的差不多了。

你可以很方便的进行查找,插入,更新,和删除。你只需要使用父类的成员变量和函数:CRecordset::m_strFilter、CRecordset::AddNew()、CRecordset::Update()、CRecordset::Delete()。

6. 用完之后记得关闭数据库。



插入CRecordView派生类

CRecordView的派生类是一个对话框。在这里我们用这个对话框作为MianWnd的一个字窗口,如图:


操作步骤:

1. 首先在ResourcesView的Dialog目录中右键,弹出快捷菜单选择Insert:


2. 在弹出的“nsert Resource”对话框中按图所示选择插入对话框为IDD_FORMVIEW,单击“New”插入对话框资源。



3. 编辑好这个对话款资源。为对话框添加类。双击对话框资源或者右键选择“Class Wizard”,确定添加类后弹出“New Class”对话框,基类(“Base Class”)选择“CRecordView”就可以了。



4. 确定后弹出如图对话框(名字N长,打字也很要命),选择前面添加的CRecordset派生类,确定。



5. 使用CRecordView派生类对话框。

首先在class View中找到CclassNameApp类,找到其成员函数“InitInstance()”,双击打开,在其中找到如下代码:

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CTestDatabaseDoc),

RUNTIME_CLASS(CMainFrame),       // main SDI frame window

RUNTIME_CLASS(CTestDatabaseView));//注意这里

AddDocTemplate(pDocTemplate);

注意看代码中的倒数第二行,将其改为刚创建的CRecordView派生类对话款的类名,单击确定,编译运行程序,就可以看见窗口的视图改变了。可以使用全局变量加if语句进行判断来动态改变窗口视图。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭