实验五 数据库应用程序的开发Word文件下载.docx
《实验五 数据库应用程序的开发Word文件下载.docx》由会员分享,可在线阅读,更多相关《实验五 数据库应用程序的开发Word文件下载.docx(13页珍藏版)》请在冰点文库上搜索。
●修改记录,设定锁定状态。
●挑选有用的记录。
●给数据库排序。
●给定参数,让数据库在运行的时候自动选择数据。
3CDatabase类
CDatabase在afxdb.h中定义。
其对象是用来连接一个数据源的。
为了使用CDatabase对象,需调用构造函数,并调用OpenEx或是Open函数,这将会打开一个连接。
当构造一个CDatabase类完成后,可以向CRecordset类的对象传递这个CDatabase类的指针。
连接数据源结束时,必须用Close函数关闭这个对象。
4RFX
RFX(RecordFieldExchange)是支持应用程序的一个交换机制,当从CRecordset类派生一个类,在交换数据的时候没有选择大容量交换的方式(BulkRFX)时,RFX机制将在数据交换中起作用。
RFX在视图和数据源之间自动交换数据,由于一次交换的数据可能不止一个,为此可能要多次调用DoFieldExchange函数,同时它也是应用程序框架和ODBC交流的媒介。
RFX机制能够安全的通过调用(例如ODBC函数SQLBindCol)来保存用户的工作。
下面代码就是【例1】工程文件中AppWizard自动加入的RFX代码,见粗斜体部分:
voidCODBCSet:
:
DoFieldExchange(CFieldExchange*pFX)
{
//{{AFX_FIELD_MAP(CODBCSet)
pFX->
SetFieldType(CFieldExchange:
outputColumn);
RFX_Long(pFX,_T("
[书籍ID]"
),m___ID);
RFX_Text(pFX,_T("
[作者]"
),m_column1);
[出版社]"
),m_column2);
[价格]"
),m_column3);
//}}AFX_FIELD_MAP
}
函数DoFieldExchange是RFX机制的中枢,任何时候应用框架需要从数据源到数据库或是从数据库到数据源,都要调用DoFieldExchange函数。
下面是CRecordset派生类的头文件,其中关于RFX机制的部分已经用粗斜体显示:
classCODBCSet:
publicCRecordset
{…
//Field/ParamData
//{{AFX_FIELD(CODBCSet,CRecordset)
longm___ID;
CStringm_column1;
CStringm_column2;
CStringm_column3;
//}}AFX_FIELD
//Overrides
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CODBCSet)
public:
……
virtualvoidDoFieldExchange(CFieldExchange*pFX);
//RFXsupport
//}}AFX_VIRTUAL
…};
5CDBException
CDBException是用来处理从其它ODBC类传过来的异常情况的。
这个类一般是和关键字CATCH连用的。
同样的用户也可以用全局函数AfxThrowDBException抛出一个异常情况
●m_nRetCode:
它包含了一个结构体RETCODE,里面包含了ODBC的错误信息的描述。
●m_strError:
包含一个描叙异常情况的字符串。
●m_strStateNativeOrigin:
包含描述异常情况的字符串
●m_strStateNativeOrigin;
如果变量包含多个错误的描述,错误会分行显示。
●CDBException类的成员变量
【例2】在【例1】的基础上增加“删除一个记录”、“更新记录”和“清除域”三个菜单项,并实现相应的操作。
1加入菜单项
2重载OnMove函数
BOOLCODBCView:
OnMove(UINTnIDMoveCommand)
{switch(nIDMoveCommand)
{caseID_RECORD_PREV:
m_pSet->
MovePrev();
if(!
m_pSet->
IsBOF())
break;
//如果移到数据库的开始,自动执行MoveFirst函数
caseID_RECORD_FIRST:
MoveFirst();
break;
caseID_RECORD_NEXT:
MoveNext();
IsEOF())break;
CanScroll())
{m_pSet->
SetFieldNull(NULL);
//清空屏幕
}
caseID_RECORD_LAST:
MoveLast();
break;
default:
ASSERT(FALSE);
//异常情况
}
UpdateData(FALSE);
//交换数据
returnTRUE;
3添加菜单响应函数
voidCODBCView:
OnDeleteRecord()//删除记录
{CRecordsetStatusm_cStatus;
try{m_pSet->
Delete();
}
catch(CDBException*m_pEx)
{AfxMessageBox(m_pEx->
m_strError);
m_pEx->
//若失败,将记录指针移到首记录
UpdateData(FALSE);
return;
GetStatus(m_cStatus);
if(m_cStatus.m_lCurrentRecord==0)
//删除了最后一个记录
else
OnUpdateDeleteRecord(CCmdUI*pCmdUI)
//删除后的刷新
{pCmdUI->
Enable(!
IsEOF());
OnUpdateRecord()
Edit();
UpdateData(TRUE);
if(m_pSet->
CanUpdate())
m_pSet->
Update();
OnUpdateUpdateRecord(CCmdUI*pCmdUI)
//刷新记录集
pCmdUI->
OnClearDomain()//清除域
【例3】在【例2】的基础上增加功能,使得程序能够向数据库中添加新记录。
增加一个菜单项“增加一个新记录”,其ID标识为ID_ADD_RECORD
在数据库中增加记录步骤:
●得到最后一条记录的ID号
●将其加1
●通过AddNew函数来添加记录
●把新的ID值设置为新增记录中的ID字段值
●用Update函数保存新记录
●调用Requery函数更新记录
●把输入控制滚动到数据库中的最后一条记录上
为了计算新的ID号,需增加CODBCSet类的成员函数GetMaxID
longCODBCSet:
GetMaxID()
{MoveLast();
//移到最后一条记录
returnm___ID;
//返回该ID值
OnAddRecord()
{CRecordset*pSet=OnGetRecordset();
//获取指向数据库的指针
if(pSet->
CanUpdate()&
&
!
pSet->
IsDeleted())
//确认对数据库的任何修改均已保存
{pSet->
if(!
UpdateData())return;
pSet->
longm_lNewID=m_pSet->
GetMaxID()+1;
//获取新的ID值
AddNew();
//添加一个新记录
m___ID=m_lNewID;
//设置新的ID标识
//保存新的记录
Requery();
//刷新数据库
//游标移到最后一条记录
//更新表单
【例4】在【例3】的基础上增加浏览记录的功能和对记录进行排序的功能。
创建对话框,通过在对话框中指定记录序号(记录序号不是记录的ID号标识)来浏览该条记录的内容。
OnMoveToRecord()
{CMoveToRecorddlgMoveTo;
//创建CMoveToRecord类的对象实例
if(dlgMoveTo.DoModal()==IDOK)
{CRecordset*pSet=OnGetRecordset();
//指向数据库记录的指针
CanUpdate()&
!
{//所有的修改保存否?
pSet->
SetAbsolutePosition(dlgMoveTo.m_RecordID);
//设置新的位置
//更新表单
}}
由于在视图中响应了对话框的操作,因此,还需要在ODBCView类的实现文件ODBCView.cpp中加入定义对话框类的头文件:
#include"
MoveToRecord.h"
同样,为了使用工具栏按钮进行快速操作,在工具栏中定义一个Move按钮,其ID与菜单项“移到第…条记录”的ID一致,Move按钮的ID为ID_MoveToRecord。
由于CRecordset类的对象或从CRecordset类继承的对象都拥有一个m_strSort成员,它决定了对记录的排序,在“记录”菜单中增加菜单项“按价格排序”,(ID_SORT_PRICE),并为它映射COMMAND消息处理函数OnSortPrice()。
OnSortPrice()
{m_pSet->
Close();
//关闭数据库
m_strSort=“价格”;
//指定排序字段
Open();
//再次打开数据库
UpdateData(FALSE);
//更新已经排序过的记录
由于用了CRecordset类的成员m_strSort,因此对数据库记录的排序不用进行太多的代码干预。
最后在工具栏中增加Sort工具按钮,实现菜单项“按价格排序”的功能。
【例5】在【例4】的基础上增加查询功能
为了编写查找功能的代码,增加菜单项“按作者查找”(ID_Search),映射的COMMAND消息处理函数为OnSearch()。
假设按“作者”字段进行查询,为菜单项“按作者查找”所映射的COMMAND消息处理函数代码如下:
OnSearch()
DoFilter("
作者"
);
DoFilter(CStringcol)
{CSearchDlgdlg;
intresult=dlg.DoModal();
if(result==IDOK)
{CStringstr=col+"
='
"
+dlg.m_Edit_Search+"
'
;
//接收查询字符串
//关闭原来的表单
m_strFilter=str;
//将查询条件赋给过滤器
//打开经过过滤的表单
intrecCount=m_pSet->
GetRecordCount();
//计算满足条件的记录数
if(recCount==0)//如果没有找到相关记录
{MessageBox(“Nomatchingrecords.”);
//关闭表单
m_strFilter;
//将过滤结果给过滤器
//据过滤结果打开表单(什么都没找到)
//不论任何情况,都更新表单
由于上述代码都是在ODBCView.cpp中,即上述操作是在视图中完成的,但查询条件是在“查询”对话框中输入的,在视图中接收了对话框的输入内容,因此,需要在ODBCView.cpp中加入代码:
SearchDlg.h"