失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > MFC 使用 ADO技术连接Access数据库

MFC 使用 ADO技术连接Access数据库

时间:2021-10-08 07:01:43

相关推荐

MFC 使用 ADO技术连接Access数据库

学了很久的MFC,于是想着使用MFC的ADO技术连接Access数据库。

记录一下,以备后面复习。

1.首先需要了解MDB数据库文件,本次示例代码连接的是MDB数据库文件。*.MDB文件是(Microsoft Database) 文件的缩写,是Access数据库文件的一种格式。就像是Word文档的.doc文件一样。

2.下面开始讲一下连接的具体步骤:

(1)新建一个对话框工程,添加相对应的控件,如下图所示:

首先最关键的步骤如下:

在stdafx.h头文件中添加如下代码,注意工程运行的x86平台下才不会出错。如果运行在x64平台下,可能会报错。笔者使用VS时运行在x64平台下,报错无法打开文件。可以参考该说明:/hbspring007/article/details/107467823

#import "C:\\Program Files (x86)\\Common Files\\System\\ado\\msado15.dll" no_namespace rename("EOF","adoEOF"),rename("BOF","adoBOF")#import "C:\\Program Files (x86)\\Common Files\\System\\ado\\msjro.dll" no_namespace rename("ReplicaTypeEnum","_ReplicaTypeEnum")

msado15.dll:主要用于对数据库进行操作。

msjro.dll:主要用于对数据库进行压缩。

第二步:

1.首先需要将msado15.tlh文件和msado15.tli文件添加到工程中。如果找不到,可从笔者工程中查找。

2.在工程的*App.h头文件中添加:连接数据库的代码如下:

_ConnectionPtr m_pConnnect;

_ConnectionPtr :为指向Connect 类对象的指针,用于连接数据库。

在工程的*App.cpp的文件的InitInstance()函数中的创建对话框之前添加如下代码:

// 初始化COM库if (!AfxOleInit()){AfxMessageBox(_T("初始化OLE DLL失败"));}HRESULT hr;try{// 创建Connection对象 hr = m_pConnnect.CreateInstance(_T("ADODB.Connection"));if (SUCCEEDED(hr)){// 下面的连接字符串中Provider是针对Access2000环境的,对于Access97环境,需要改为Microsoft.Jet.OLDDB.3.51.hr = m_pConnnect->Open(_T("Provider = Microsoft.Jet.OLEDB.4.0;Data Source= AdoData.mdb"), "", "", adModeUnknown); // 连接数据库}}catch (_com_error e) // 捕捉异常{CString errormessage;errormessage.Format(_T("连接数据库失败!\r\n错误信息:%s"), e.ErrorMessage());AfxMessageBox(errormessage);///显示错误信息}

注意:上面的m_pConnect及使用了 “.” 操作符,又指针的行为间接引用"->“,是因为_ConnectionPtr类重载了”->"操作符。

首先,我们需要先初始化COM库。

其中的Data Source = AdoData.mdb数据库是预先做好的数据库。使用_ConnectionPtr::Open()函数打开数据库。

第三步:在***Dlg.h 文件中添如下代码:

为对话框关联成员变量如下:

_RecordsetPtr m_pRecordset;UINT m_nID;UINT m_nAge;CString m_strUserName;// DataTime 控件成员变量COleDateTime m_tBirthday;// CListCtrl 控件CListCtrl m_UserList;// 用于判断是否成功读取数据库数据BOOL m_bSuccess;// 获取CListCtrl 控件中当前选择的行int m_nCurSelect;// 判断在添加数据或者选择数据后是否保存数据BOOL m_bAutoSave;// 定义四个 _variant_t 类对象_variant_t m_vID, m_vUserName, m_vAge, m_vBirthday;

_RecordsetPtr: 用于访问数据库中的数据。具体的用法可以参考MSDN,网址如下:MSDN 关于ADO 的介绍

其中使用了_variant_t类,关于这个类的介绍,大家也可以参考前面的MSDN.

_variant_t类:封装和管理了Variant类型的数据。

另外再添加两个函数用于保存修改和删除原来的数据。

在工程对话框的***::OnInitialDialog()函数中添加如下代码:

// 为列表控件添加列m_UserList.SetExtendedStyle(m_UserList.GetExtendedStyle()|LVS_EX_FULLROWSELECT| LVS_EX_GRIDLINES);m_UserList.InsertColumn(0,_T("ID"),LVCFMT_LEFT,60);m_UserList.InsertColumn(1, _T("用户名"), LVCFMT_LEFT,100);m_UserList.InsertColumn(2, _T("年龄"), LVCFMT_LEFT,60);m_UserList.InsertColumn(3, _T("生日"), LVCFMT_LEFT,120);try{// 创建一个新的连接数据库实例m_pRecordset.CreateInstance(_T("ADODB.Recordset"));// 使用SQL语句,用来查询users这个表的内容m_pRecordset->Open("SELECT * FROM users",_variant_t((IDispatch*)theApp.m_pConnnect,TRUE),adOpenStatic,adLockOptimistic,adCmdText);m_bSuccess = TRUE;// EOF(End of File:指示当前位置位于Recordset对象的最后一个记录之后)// 使用BOF(Before of File):bof表示rs当前的指针是指在了数据集的前面;使用BOF和EOF可用于判断Recordset对象是否包含记录// 或者从一个记录移到另一个记录时是否超出Recordset对象的限制。while(!m_pRecordset->adoEOF) {// GetCollect()函数的作用:用来获取收集的字符串,例如就是用来获取_T("")字符串的vID = m_pRecordset->GetCollect(_T("id"));vUserName = m_pRecordset->GetCollect(_T("username"));vAge = m_pRecordset->GetCollect(_T("age"));vBirthdayr = m_pRecordset->GetCollect(_T("birthday"));// 在控件中插入新行nItem = m_UserList.InsertItem(0xffff,(_bstr_t)vID);// 在已经存在的行中设置信息m_UserList.SetItem(nItem, 1, 1, (_bstr_t)vUserName,NULL,0,0,0);m_UserList.SetItem(nItem, 2, 1, (_bstr_t)vAge, NULL, 0, 0, 0);m_UserList.SetItem(nItem, 3, 1, (_bstr_t)vBirthdayr, NULL, 0, 0, 0);m_pRecordset->MoveNext(); }}catch (_com_error e){AfxMessageBox(_T("读取数据库失败!"));}

上面对话框中,添加行按钮的实现代码如下:

UpdateData();if (m_strUserName.GetLength() > 0){// 创建可更新Recordset对象的新纪录m_pRecordset->AddNew();// 在65535行中插入_T("")m_nCurSelect = m_UserList.InsertItem(0xffff,_T(""));SaveData();m_UserList.SetItemState(m_nCurSelect,LVIS_SELECTED| LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);m_UserList.SetHotItem(m_nCurSelect);m_UserList.SetFocus();}else{AfxMessageBox(_T("请输入用户名"));}

调用的SaveData()函数的代码如下:

if (!m_pRecordset->adoEOF && m_nCurSelect >= 0 && m_bAutoSave){m_vID = (long)m_nID;m_vUserName = m_strUserName;m_vAge = (long)m_nAge;m_vBirthday = m_tBirthday;// PutCollect(A,B)函数的作用是将B中的数据添加到数据库A中m_pRecordset->PutCollect(_T("id"),m_vID);m_pRecordset->PutCollect(_T("username"), m_vUserName);m_pRecordset->PutCollect(_T("age"), m_vAge);m_pRecordset->PutCollect(_T("birthday"), m_vBirthday);// 将当前修改的值插入到当前选择行中m_UserList.SetItem(m_nCurSelect,0,LVIF_TEXT,(_bstr_t)m_vID,NULL,0,0,0);m_UserList.SetItem(m_nCurSelect, 1, LVIF_TEXT, (_bstr_t)m_vUserName, NULL, 0, 0, 0);m_UserList.SetItem(m_nCurSelect, 2, LVIF_TEXT, (_bstr_t)m_vAge, NULL, 0, 0, 0);m_UserList.SetItem(m_nCurSelect, 3, LVIF_TEXT, (_bstr_t)m_vBirthday, NULL, 0, 0, 0);}

与之相对的LoadData()函数的代码如下:

m_pRecordset->Move(m_nCurSelect, _variant_t((long)adBookmarkFirst));m_vID = m_pRecordset->GetCollect(_T("id"));m_vUserName = m_pRecordset->GetCollect(_T("username"));m_vAge = m_pRecordset->GetCollect(_T("age"));m_vBirthday = m_pRecordset->GetCollect(_T("birthday"));m_nID = m_vID.lVal;m_strUserName = (LPCTSTR)(_bstr_t)m_vUserName;m_nAge = m_vAge.lVal;m_tBirthday = m_vBirthday;UpdateData(FALSE);

前面对话框中删除按钮的实现代码如下:

m_bAutoSave = FALSE;if (m_nCurSelect >= 0){// 删除当前选中行m_UserList.DeleteItem(m_nCurSelect);int nCount = m_UserList.GetItemCount();if (nCount <= m_nCurSelect)m_nCurSelect = nCount - 1; // 删除之后重新设置选中行// 设置当前指针指向的记录会被删除m_pRecordset->Delete(adAffectCurrent);// 将当前记录集指针移到下一个记录m_pRecordset->MoveNext();if (nCount > 0)LoadData();// 设置当前选中行,为选中状态m_UserList.SetItemState(m_nCurSelect, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);m_UserList.SetFocus();}m_bAutoSave = TRUE;

点击ListCtrl列表控件通知消息的代码如下:

void CMFCTESTADODlg::OnLvnItemchangedUserList(NMHDR* pNMHDR, LRESULT* pResult){// NMHDR:包含有关此通知消息的信息结构体// LPNMLISTVIEW:专属于ListView类型的通知消息结构体,包含了NMHDR,换一个控件会有不同的形式LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);// TODO: 在此添加控件通知处理程序代码// 判断是否选择当前控件的行if (pNMLV->uNewState & LVIS_SELECTED){UpdateData();SaveData();// 设置当前行为选中行m_nCurSelect = pNMLV->iItem;LoadData();}*pResult = 0;}

最后确定按钮的实现代码如下:

if (m_bSuccess){// Update:保存对于对于当前记录集对象,即m_pRecordset数据的修改m_pRecordset->Update();// 关闭一个对象m_pRecordset->Close();}

该Demo中用到的主要技术有:

_ConnectPtr类和_RecordsetPtr类。

Connect::CreateInstance;

Connect::Open;

Recordset::CreateInstance;

Recordset::Open;

Recordset的adoEOF和adoBOF成员变量;

Recordset::GetCollect();

Recordset::MoveNext();

Recordset::AddNew();

Recordset::Delete();

Recordset::Update();

Recordset::Close();

Recordset::Move();

这些函数的具体用法可以参考微软的官方文档:

Recordset Methods

本Demo的源码下载如下:Gitee

如果觉得《MFC 使用 ADO技术连接Access数据库》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。