1、MFC 下使用下使用 ADO 读写读写 Access 数据库实例数据库实例 一、一、原型系统描述原型系统描述.2 二、二、数据库表设计数据库表设计.2 三、三、数据库编程数据库编程.2 1.新建新建 MFC 基于对话框项目基于对话框项目.2 2.用用#import 指令引入指令引入 ADO 类型库类型库.2 3.创建数据库操作类创建数据库操作类 CADODatabase.3 3.1 为为 CADODatabase 添加两个成员变量添加两个成员变量.3 3.2 添加添加 OpenDatabase 函数函数.3 3.3 添加添加 CloseDatabase 函数函数.4 3.4 添加添加 Sele
2、ct 函数函数.5 3.5 添加添加 Execute 函数函数.6 四、四、MFC 界面编程界面编程.6 1.在对话框中添加控件在对话框中添加控件.6 2.在程序启动时初始化列表框,并连接数据库在程序启动时初始化列表框,并连接数据库.7 2.1 初始化列表框初始化列表框.7 2.2 连接数据库连接数据库.7 3.添加查询功能添加查询功能.8 4.添加新增记录功能添加新增记录功能.9 五、五、使用使用 Datagrid ActiveX 控件控件.10 1.添加添加 Datagrid 控件控件.10 2.创建数据库创建数据库.11 3.创建数据库操作类创建数据库操作类 CADODatabase.1
3、2 4.使用使用 Datagrid.12 4.1 绑定数据源绑定数据源.12 4.2 添加记录添加记录.13 说明:本文以“学生信息管理”系统雏形为例子,介绍在 MFC 下如何使用 ADO 连接数据库编程,并给出示例代码。下面内容第一至四节介绍如何采用 ADO 连接数据库、关闭数据、执行 sql 语句及如何用另一种方式执行常用的 select 语句。第五节介绍如何使用Datagrid 控件:建立_RecordsetPtr 对象与 Datagrid 控件之间的绑定,通过改变_RecordsetPtr对象的内容更新数据库表的记录。第一至四节的内容请参考代码“CtrlListDatabase.rar
4、第五节内容请参考“Datagrid.rar”请同学们结合 ADO.NET 课程内容自主学习,将所学到的技术应用到项目实训中。一、一、原型系统描述原型系统描述 本程序为一个学生信息管理系统雏形。程序界面如下图左图所示。用户在姓名栏输入查询字段,列表框中列出查询结果。如下图右图所示。用户点击新增记录按钮新增学生信息记录。二、二、数据库表设计数据库表设计 建立 Access 文件 test.mdb,创建 student 表,表中字段名称、数据类型及各字段的说明设置如下 三、三、数据库编程数据库编程 1.新建新建 MFC 基于对话框项目基于对话框项目 新建 MFC 基于对话框项目。本例中对项目命名
5、为 CtrlListDatabase。2.用用#import 指令引入指令引入 ADO 类型库类型库 为了引入 ADO 类型库,需要在项目的 stdafx.h 文件中加入如下语句:#import C:Program FilesCommon FilesSystemadomsado15.dll no_namespace rename(EOF,adoEOF)注意添加的位置在#endif /_AFX_NO_AFXCMN_SUPPORT 之后 3.创建数据库操创建数据库操作类作类 CADODatabase 3.1 为为 CADODatabase 添加两个成员变量添加两个成员变量 _ConnectionP
6、tr m_pConnection;_RecordsetPtr m_pRecordset;其中 m_pConnection 是一个指向 Connection 对象的指针,通过它来连接数据库。m_pRecordset 是一个指向记录集合的指针,从数据库查询得到的结果放在 m_pRecordset 中。3.2 添加添加 OpenDatabase 函数函数 功能:连接数据库 输入:数据库连接串 strConnection(其含义见其含义见第四部分第二步第四部分第二步中中 2.2 的的解释解释)输出:TRUE,如果成功连接数据库,FALSE,如果连接数据库失败 BOOL CADODatabase:Ope
7、nDatabase(CString strConection)HRESULT hr=:CoInitialize(NULL);/初始化 COM if(!SUCCEEDED(hr)/初始化失败 return FALSE;_bstr_t strConnect(strConection);try /创建 Connection 对象 hr=m_pConnection.CreateInstance(ADODB.Connection);if(SUCCEEDED(hr)/连接数据库 if(SUCCEEDED(m_pConnection-Open(strConnect,adModeUnknown)return
8、TRUE;catch(_com_error e)TRACE(_T(连接数据库发生错误%sn),e.ErrorMessage();return FALSE;上述代码中,通过 Connection 对象的 Open 方法来进行连接数据库的,下面是该方法的原型:HRESULT Connection15:Open(_bstr_t ConnectionString,_bstr_t UserID,_bstr_t Password,long Options);上述函数中参数 ConnectionString 为连接字串;参数 UserID 是用户名;参数 Password是登陆密码;在本例子中,数据库的用户
9、名和密码均没创建,所以去空值?。参数 Options是连接选项,用于指定 Connection 对象对数据的更新许可权,一般情况下 Options 可以是如下几个常量:adModeUnknown 缺省。当前的许可权未设置 adModeRead 只读 adModeWrite 只写 adModeReadWrite 可以读写 adModeShareDenyRead 阻止其它 Connection 对象以读权限打开连接 adModeShareDenyWrite 阻止其它 Connection 对象以写权限打开连接 adModeShareExclusive 阻止其它 Connection 对象以读写权限
10、打开连接 adModeShareDenyNone 阻止其它 Connection 对象以任何权限打开连接 3.3 添加添加 CloseDatabase 函数函数 功能:关闭数据库连接 返回:TRUE,如果成功关闭,否则 FALSE。BOOL CADODatabase:CloseDatabase()if(m_pConnection=NULL)/如果连接已经为空 return TRUE;try m_pConnection-Close();m_pConnection=NULL;return TRUE;catch(_com_error e)TRACE(_T(关闭数据库发生错误:%sn),e.Error
11、Message();return FALSE;3.4 添加添加 Select 函数函数 功能:返回查询结果 输入:查询语句字符串 sql 输出:查询结果集合 方法一:方法一:直接用 Recordset 对象进行查询取得记录集 _RecordsetPtr CADODatabase:Select(CString sql)_bstr_t CommandText(sql);/生成要执行的 sql 语句字符串 m_pRecordset.CreateInstance(ADODB.Recordset);/生成_RecordsetPtr 实例 m_pRecordset-Open(CommandText,/连接
12、数据库查询 m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockBatchOptimistic,adCmdText);return m_pRecordset;其中 Open 方法原型如下:HRESULT Recordset15:Open(const _variant_t&Source,const _variant_t&ActiveConnection,enum CursorTypeEnum CursorType,enum LockTypeEnum LockType,long Options)上述函数中参数 Source 是数据查询字符串;参数
13、 ActiveConnection 是已经建立好的连接(我们需要用 Connection 对象指针来构造一个_variant_t 对象);参数 CursorType 光标类型,它可以是以下值之一;请看这个枚举结构:enum CursorTypeEnum adOpenUnspecified=-1,/不作特别指定 adOpenForwardOnly=0,/前滚静态光标。这种光标只能向前浏览记录集,比如用 MoveNext向前滚动,这种方式可以提高浏览速度。但诸如BookMark,RecordCount,AbsolutePosition,AbsolutePage 都不能使用 adOpenKeyset
14、1,/采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的操作对你是可见的。adOpenDynamic=2,/动态光标。所有数据库的操作都会立即在各用户记录集上反应出来。adOpenStatic=3/静态光标。它为你的记录集产生一个静态备份,但其它用户的新增、删除、更新操作对你的记录集来说是不可见的。;参数 LockType 表示数据库的锁定类型,它可以是以下值之一,请看如下枚举结构:enum LockTypeEnum adLockUnspecified=-1,/未指定 adLockReadOnly=1,/只读记录集 adLockPessimistic=2,悲观锁定方式。
15、数据在更新时锁定其它所有动作,这是最安全的锁定机制 adLockOptimistic=3,乐观锁定方式。只有在你调用 Update 方法时才锁定记录。在此之前仍然可以做数据的更新、插入、删除等动作 adLockBatchOptimistic=4,乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。;方法二:方法二:利用 Command 对象来执行 SQL 命令 _RecordsetPtr CADODatabase:Select(CString sql)_CommandPtr m_pCommand;m_pCommand.CreateInstance(ADODB.Command
16、);_variant_t vNULL;vNULL.vt=VT_ERROR;vNULL.scode=DISP_E_PARAMNOTFOUND;/定义为无参数 m_pCommand-ActiveConnection=m_pConnection;/非常关键的一句,将建立的连接赋值给它 m_pCommand-CommandText=SELECT*FROM users;/命令字串 m_pRecordset=m_pCommand-Execute(&vNULL,&vNULL,adCmdText);return m_pRecordset;3.5 添加添加 Execute 函数函数 功能:执行 sql 语句(例
17、如 Insert、Update 操作等)输入:sql 语句字符串 返回值:TRUE,如果成功执行。BOOL CADODatabase:Execute(CString sql)_bstr_t CommandText(sql);_variant_t RecordsAffected;m_pConnection-Execute(CommandText,&RecordsAffected,adCmdText);return TRUE;四、四、MFC 界面界面编程编程 1.在对话框中添加控件在对话框中添加控件 控件 ID 关联变量类型 关联变量 说明 编辑框 IDC_EDIT_NAME CString m_
18、strQueryName 查询姓名编辑框 列表控件 IDC_LIST_STUDENT_INFO CListCtrl m_listCtrl 查询记录列表狂 将列表框控件的 View 属性(在 Style 选项卡下)设置为 Report 2.在程序启动时初始化列表框在程序启动时初始化列表框,并连接数据库,并连接数据库 在 CCtrlListDatabaseDlg:OnInitDialog()函数中添加两部分代码:2.1 初始化列表框初始化列表框 m_ListCtrl.SetExtendedStyle(LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT|LVS_EX
19、TRACKSELECT);/设置列表框的样式 CString header4=姓名,性别,出生日期,已修学分;/增加列表头部 for(int i=0;i adoEOF)/遍历查询结果集合,将每条结果在列表框中显示 /pRecordset-GetCollect(name)取出当前记录的 Name 字段的值。因为 Name 字段的值是字符串类型,所以取 bstrVal 属性获得字段值。CString temp=pRecordset-GetCollect(name).bstrVal;/往列表框新增一条记录 m_ListCtrl.InsertItem(row,temp);/pRecordset-Ge
20、tCollect(gender)取出当前记录的 gender 字段的值。因为 gender字段的值整数类型,所以取 lVal 属性获得字段值。gender=pRecordset-GetCollect(gender).lVal;if(gender=0)m_ListCtrl.SetItemText(row,1,男);else m_ListCtrl.SetItemText(row,1,女);/pRecordset-GetCollect(birthday)取出当前记录的 birthday 字段的值。因为birthday 字段的值为时间类型,所以取 date 属性获得字段值。time=pRecordse
21、t-GetCollect(birthday).date;temp=time.Format(%Y-%m-%d);m_ListCtrl.SetItemText(row,2,temp);/pRecordset-GetCollect(credit)取出当前记录的 credit 字段的值。因为 credit 字段的值为整数类型,所以取 lval 属性获得字段值。credit=pRecordset-GetCollect(credit).lVal;temp.Format(%d,credit);m_ListCtrl.SetItemText(row,3,temp);row+;pRecordset-MoveNex
22、t();4.添加新增记录功能添加新增记录功能 新增编辑框,控件摆放如下图所示。为该编辑框新建一个关联的类 CEditInfoDlg 控件 ID 关联变量类型 关联变量 说明 编辑框 IDC_EDIT_NAME CString m_name 编辑姓名 选择按钮 IDC_RADIO_MALE IDC_RADIO_FEMALE Int m_gender 选择性别 日期控件 IDC_DATETIMEPICKER_BIRTHDAY CTime m_birthday 选择出生年月日 编辑框 IDC_EDIT_CREDIT Int m_credit 编辑学分 在 CCtrlListDatabaseDlg 中
23、增加“新增按钮”响应函数 void CCtrlListDatabaseDlg:OnButtonAdd()/TODO:Add your control notification handler code here CEditInfoDlg dlg;if(IDOK=dlg.DoModal()/根据用户在编辑框输入的信息生成 sql 语句 CString sql=insert into student(name,gender,birthday,credit)values(;sql+=+dlg.m_name+;CString gender;gender.Format(%d,dlg.m_gender);
24、sql+=,+gender;CString time=dlg.m_birthday.Format(%Y-%m-%d);sql+=,+time+;CString strCredit;strCredit.Format(%d,dlg.m_credit);sql+=,+strCredit+);m_database.Execute(sql);五、五、使用使用 Datagrid ActiveX 控件控件 本节演示如何使用 Datagrid 控件显示数据。新建项目基于对话框 MFC 项目,命名为Datagrid。界面控件设置同上,区别是采用 Datagrid 控件代替 List Control 控件。1.添
25、加添加 Datagrid 控件控件 Datagrid 控件的添加:菜单栏-项目(Project)-添加至项目(Add to Project)-组件和控件(Components and Controls)选择 Registered ActiveX Controls,Microsoft DataGrid Control 点击插入(Insert),确定。此时弹出一个确认框 不作修改,点击确定。然后点击关闭(Close)关闭文件对话框。此时控件列表中会多了一个红色的控件-Datagrid 控件。将 Datagrid 控件拉到对话框界面。控件 ID 设为 ID_DATAGRID_RESULT,Capti
26、on 设为“查询结果”,关联变量类型为 CDatagrid,变量名为 m_datagrid。其余控件设置同上。如图所示。2.创建数创建数据库据库 新建数据库 test.mdb,创建 student 表。3.创建数据库操作类创建数据库操作类 CADODatabase 具体操作同上。在窗口创建时,建立数据库连接。即在 CDatagridDlg:OnInitDialog()函数中添加代码:CString strConnection=Provider=Microsoft.Jet.OLEDB.4.0;Data Source=;strConnection+=test.mdb;m_database.Open
27、Database(strConnection);4.使用使用 Datagrid 4.1 绑定数据源绑定数据源 给查询按钮添加相应函数 OnBUTTONQuery。void CDatagridDlg:OnBUTTONQuery()/TODO:Add your control notification handler code here UpdateData();/根据查询条件生成 sql 语句 CString sql=select*from student where name like%;sql+=m_QueryName;sql+=%;/获得查询结果 _RecordsetPtr pRecord
28、set=m_database.Select(sql);m_QueryResult.SetRefDataSource(NULL);/绑定数据源 m_QueryResult.SetRefDataSource(LPUNKNOWN)pRecordset);m_QueryResult.SetColumnHeaders(TRUE);_variant_t vIndex;CColumn col=NULL;/设置显示数据列 vIndex=long(0);col=m_QueryResult.GetColumns().GetItem(vIndex);col.SetWidth(50);/设置列宽度 col.SetCa
29、ption(id);col.SetVisible(FALSE);/隐藏主键列不显示 vIndex=long(1);col=m_QueryResult.GetColumns().GetItem(vIndex);col.SetWidth(50);/宽度 col.SetCaption(姓名);vIndex=long(2);col=m_QueryResult.GetColumns().GetItem(vIndex);col.SetWidth(50);/宽度 col.SetCaption(性别);vIndex=long(3);col=m_QueryResult.GetColumns().GetItem(
30、vIndex);col.SetWidth(80);/宽度 col.SetCaption(出生日期);vIndex=long(4);col=m_QueryResult.GetColumns().GetItem(vIndex);col.SetWidth(50);/宽度 col.SetCaption(学分);m_QueryResult.Refresh();4.2 添加记录添加记录 添加记录代码如下:CEditInfoDlg dlg;if(IDOK=dlg.DoModal()/获得数据源记录集。_RecordsetPtr pRecordset=m_database.m_pRecordset;/注意:调
31、用下述代码前,需确保 pRecordset 与某张数据库表内的数据绑定 /新增一条记录 pRecordset-AddNew();/设置姓名字段 pRecordset-PutCollect(name,_variant_t(dlg.m_name);/设置性别字段 CString gender;if(dlg.m_gender=0)gender=男;else gender=女;pRecordset-PutCollect(gender,_variant_t(gender);/设置出生日期字段 CString time=dlg.m_birthday.Format(%Y-%m-%d);pRecordset-PutCollect(birthday,_variant_t(time);/设置学分字段 CString credit;credit.Format(%d,dlg.m_credit);pRecordset-PutCollect(credit,_variant_t(credit);/添加记录 pRecordset-Update();






