下面来写一个简单的小程序,程序实现的功能是能够动态的连接一个在电脑上建好的Access数据表,并能够实现插入、删除、替换数据的功能!
下面来看一下主框架界面:
这个主界面比较简单,就是四个按钮,是用来添加消息响应函数的,主要是实现数据库连接的功能,当按下SELECT测试按钮后,进行数据库连接,并将选定的数据通过对话框显示出来,以示连接成功。当按下INSERT测试按钮后,向Access数据表中插入一行数据,插入成功后显示状态,依次类推,当按下UpdateData测试后,将数据表中的某项数据更新,并显示成功状态,当按下DELETE测试后,将数据表中的某项指定数据删除,并显示成功状态!显示如下:
下面我们先介绍下数据库连接的一些基本知识:
ODBC(Open Datebase Conectivity)即开放式数据库互联,它是微软公司开放服务结构(WOSA,Windows Open Services Architecture)中有关数据库的一个组成部分,它建立了一组规范,并提供了一组对数据库访问的标准API(应用程序编程接口)。这些API利用SQL来完成其大部分任务。ODBC本身也提供了对SQL语言的支持,用户可以直接将SQL语句送给ODBC。
MFC的ODBC类对较复杂的ODBC API进行了封装,提供了简化的调用接口。MFC的ODBC主要包括以下几个类:
数据源是位于一些数据库管理系统(DBMS)的数据的指定实例,包括MicrosoftSQLServer 和MicrosoftAccess和BorlanddBASE和xBASE。为使用CDatabase,构造一个CDatabase对象并调用它的OpenEx成员函数。这打开了一个连接。在接着构造CRecordset对象以操纵连接的数据源时,向CDatabase对象传递记录集构造程序指针。完成使用连接时调用Close成员函数并销毁CDatabase对象。Close关闭以前没有关闭的任何记录集。
下面我们来看具体操作:
首先我们写一个类来包含一系列连接数据库的操作:
#ifndef ACCESS_H_H_H
#define ACCESS_H_H_H
#include //MFC ODBC数据库类的定义文件
class Access
{
public:
Access(void); //类的构造函数
virtual ~Access(void); //类的析构函数
BOOL Connect(LPCTSTR szDbPath); //实现数据源的动态注册及实现CDatabase类对象与数据源的连接,并 将CDatabase类对象的指针传递给CRecordset对象,以便该对象在后 面创建记录集
void DisConnect(); //断开数据集指针及数据源对象与数据源的链接
long Select(LPCTSTR szSQL); //CRecordset类的对象指针调用函数创建记录集,返回的值是指向当前的 记录
CString GetField(const SHORT fieldIndex); //得到记录集中的字段值,重载函数,形参分别是索引值 和名称
CString GetField(LPCTSTR fieldName);
BOOL Qurey(LPCTSTR szSQL); //执行一条SQL语句
static Access* GetInstance(); //单例模式,每次只是用一个Access对象
private:
CDatabase m_Database; //将CDatabase类的对象作为其成员变量
CRecordset *m_pRecordSet; //将CRecordset类的对象指针作为其成员变量
};
#endif
该类的源文件下的几个重要函数代码:
#pragma comment(lib,"odbccp32.lib") //指定连接要使用的库,该库中包含SQLConfigDataSource函数
#include
//实现类的单例模式
Access* Access::GetInstance() {
static Access instance;
return &instance;}
BOOL Access::Connect(LPCTSTR szDbPath)
{
CString csTemp;
csTemp.Format(_T("DSN=%s;DBQ=%s"),_T("my_db"),szDbPath);//DSN:新数据源名称;DBQ:数据源地址;
//动态注册数据源
//SQLConfigDataSource()函数可以动态的增加,修改和删除数据源!
if(SQLConfigDataSource(NULL,ODBC_ADD_DSN,_T("Microsoft Access Driver (*.mdb)"),
(LPCTSTR)csTemp.GetBuf fer(256)))
{
TRACE("/**********动态注册数据源成功!***********/\n");//调试时TRACE宏信息输出到VC IDE环境 的输出窗口;
}
else
{
TRACE("/**********创建DSN时出现错误!!***********/\n");
return FALSE;
}
//创建对象与数据源的连接
if(m_Database.IsOpen()) //如果CDatabase对象当前与数据源连接,则返回非零
{
m_Database.Close(); //关闭数据源连接
}
BOOL bOpenFlag;
//assert宏的原型定义在中,其作用是如果它的条件返回错误,则终止程序执行
ASSERT(TRUE == (bOpenFlag = m_Database.OpenEx(_T("DSN=my_db"),CDatabase::noOdbcDialog)));
//使用CRecordset对象操作数据源时,必须将CDatabase对象的指针传递给他的构造函数,
//并调用成员函数OPEN()创建记录集。
if(m_pRecordSet != NULL)
{
if(m_pRecordSet->IsOpen())
{
m_pRecordSet->Close();
}
delete(m_pRecordSet);
m_pRecordSet = NULL;
}
if(m_pRecordSet == NULL)
{
m_pRecordSet = new CRecordset(&m_Database);
}
return bOpenFlag;
}
//关闭数据库
void Access::DisConnect()
{
if(m_pRecordSet != NULL)
{
if(m_pRecordSet->IsOpen())
{
m_pRecordSet->Close();
}
delete(m_pRecordSet);
m_pRecordSet = NULL;
}
if(m_Database.IsOpen())
{
m_Database.Close();
}
}
long Access::Select(LPCTSTR szSQL)
{
if(m_pRecordSet->IsOpen())
{
m_pRecordSet->Close();
}
BOOL searchResult = m_pRecordSet->Open(CRecordset::snapshot,szSQL,CRecordset::none);
if(TRUE == searchResult)
{
return m_pRecordSet->GetRecordCount();
}
else
{
return 0;
}
}
BOOL Access::Qurey(LPCTSTR szSQL)
{
/**在c++中,可以直接抛出异常之后自己进行捕捉处理,
*可以在任何自己得到不想要的结果的时候进行中断,
*比如在进行数据库事务操作的时候,如果某一个语句返回SQL_ERROR则直接抛出异常,
*在catch块中进行事务回滚)
**/
TRY
{
m_Database.ExecuteSQL(szSQL); //执行一条SQL语句。不返回数据记录
}
CATCH(CDBException,e)
{
return FALSE;
}
END_CATCH;
return TRUE;
}
CString Access::GetField(const SHORT fieldIndex)
{
CString csTemp;//要存储字段的值 对象的引用
m_pRecordSet->GetFieldValue(fieldIndex,csTemp);
return csTemp;
}
CString Access::GetField(LPCTSTR fieldName )
{
CString csTemp;
m_pRecordSet->GetFieldValue(fieldName, csTemp);
return csTemp;
}
下面我们再看看在按钮的响应函数中是如何实现对数据的操作的:
void CExercise7Dlg::OnBnClickedBtnSelect() // 连接测试
{
// TODO: Add your control notification handler code here
Access *m_access; //构造ACCESS类的一个对象
m_access = Access::GetInstance();
if(TRUE == m_access->Connect(_T(".\\manage.mdb"))) // 判断是否成功连接数据库
{
MessageBox(_T("数据连接成功!"));
}
int nResult; //获取一个给定的字段值,并在消息盒中显示该字段值的第一行数据,意思数据连接成功。
if((nResult = m_access->Select(_T("SELECT * FROM `manageTable`"))) > 0)
{
MessageBox(m_access->GetField((short)0).GetBuffer(256));
MessageBox(m_access->GetField(_T("classes")).GetBuffer(256));
}
else
{
MessageBox(_T("数据库查询结果数为0"));
}
m_access->DisConnect();
}
void CExercise7Dlg::OnBnClickedBtnInsert() // 插入数据测试
{
Access *m_access;
m_access = Access::GetInstance();
if(TRUE == m_access->Connect(_T(".\\manage.mdb")))
{
MessageBox(_T("数据连接成功!"));
}
CString strSQL; // 此处为SQL语句的标准格式,详情请参考SQL语句。
strSQL.Format(_T("INSERT INTO `manageTable`(`studynum`, `duty`, `name`, `task`, `classes`, `phone`, `qq`, `address`)\
VALUES('%s','%s','%s','%s','%s','%s','%s','%s')"),
TEXT("56"),
TEXT("组员"),
TEXT("大头"),
TEXT("软件"),
TEXT("机制0805"),
TEXT("32432324234"),
TEXT("32423"),
TEXT("华中科技大学"));
if(TRUE == m_access->Qurey(strSQL.GetBuffer(256)))
{
MessageBox(_T("插入数据成功"));
}
}
下面的几个按钮的消息响应就类似啦,在此就不啰嗦了。
好了,至此MFC数据库的连接操作就此结束了,现在来做一个总结: