目录
1 新建数据库
2 添加和编辑对话框资源
3 初始化OLE/COM库
4 创建Connection对象、打开数据源,建立同数据源的连接
5 执行SQL命令、使用结果集
6 终止连接
1 新建数据库
新建一简单Access数据库,内有一studentinfo表。
2 添加和编辑对话框资源
创建一个基于对话框的MFC工程,工程名为Ch15Demo1。
单选按钮“添加记录”的属性需要勾选“组”才可以关联变量,如下:
对话框中的控件变量如下:
“添加记录”按钮默认为选中状态,代码如下:
CCh15Demo1Dlg::CCh15Demo1Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CCh15Demo1Dlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CCh15Demo1Dlg)
m_StuNo = _T("");
m_StuName = _T("");
m_StuAddress = _T("");
m_StuTel = _T("");
m_Status = _T("");
m_radio = 0;//添加记录单选按钮选中
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
初始化其它按钮状态:
BOOL CCh15Demo1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
GetDlgItem(IDC_REMOVE)->EnableWindow(false);//禁用删除按钮
GetDlgItem(IDC_CHECKIN)->EnableWindow(false);//禁用提交按钮
//禁用导航按钮控件
GetDlgItem(IDC_FIRST)->EnableWindow(false);//禁用第一条按钮
GetDlgItem(IDC_NEXT)->EnableWindow(false);//禁用下一条按钮
GetDlgItem(IDC_PREV)->EnableWindow(false);//禁用上一条按钮
GetDlgItem(IDC_LAST)->EnableWindow(false);//禁用最后一条按钮
return TRUE;
}
3 初始化OLE/COM库
ADO是一组动态链接库,因此在使用之前还必须导入ADO并且初始化。
// : include file for standard system include files,
#import "C:\program files\common files\system\ado\m; no_namespace rename("EOF","adoEOF")
// C : implementation file
BOOL CCh15Demo1App::InitInstance()
{
AfxEnableControlContainer();
//初始化OLE DLLs
if (!AfxOleInit())
{
AfxMessageBox("初始化OLE DLL失败!");
return FALSE;
}
...
}
4 创建Connection对象,打开数据源,建立同数据源的连接
创建一个Connection对象,定义用于连接的字符串信息,包括数据源名称、用户ID、口令、连接超时、默认数据库以及光标的位置。一个Connection对象代表了同数据源的一次会话。
在头文件CH15Demo1Dlg.h中定义一处指向Connection对象的指针:
// C : header file
class CCh15Demo1Dlg : public CDialog
{
public:
_ConnectionPtr m_pConnection;//连接对象
_RecordsetPtr m_pRecordset; //记录集对象
...
}
在文件C的OnInitDialog()中通过Connection对象连接创建的数据库S:
// C : implementation file
BOOL CCh15Demo1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
HRESULT hr;
try
{
hr = m_("ADODB.Connection");//创建Connection对象
if(SUCCEEDED(hr))
{
hr = m_pConnection->Open("Provider=Micro;Data Source=S","","",adModeUnknown);///连接数据库
//hr = m_pConnection->Open("studb","","",adModeUnknown);
}
}
catch(_com_error e)///捕捉异常
{
CString errormessage;
errorme("连接数据库失败!\r\n错误信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage);///显示错误信息
}
_variant_t RecordsAffected;
return TRUE;
}
5 执行SQL命令、使用结果集。
5.1 自定义一个显示记录的函数
// C : header file
class CCh15Demo1Dlg : public CDialog
{
protected:
void ShowRecord();//显示记录
}
// C : implementation file
void CCh15Demo1Dlg::ShowRecord()
{
m_StuNo=(char*)_bstr_t(m_pRecordset->GetCollect("stuNo"));
m_StuName=(char*)_bstr_t(m_pRecordset->GetCollect("stuname"));
m_StuAddress=(char*)_bstr_t(m_pRecordset->GetCollect("stuaddress"));
m_StuTel=(char*)_bstr_t(m_pRecordset->GetCollect("stuphone"));
UpdateData(false);
}
5.2 各控件消息响应函数
先在头文件中定义公共指针和变量
// C : header file
class CCh15Demo1Dlg : public CDialog
{
public:
_ConnectionPtr m_pConnection;//连接对象
_RecordsetPtr m_pRecordset; //记录集对象
int count;//记录数
int curNo;//当前操作记录
...
}
// C : implementation file
void CCh15Demo1Dlg::OnRadio1()
{
// TODO: Add your control notification handler code here
m_radio=0;
GetDlgItem(IDC_ADD)->EnableWindow(true);//激活添加按钮
GetDlgItem(IDC_REMOVE)->EnableWindow(false);//禁用删除按钮
GetDlgItem(IDC_CHECKIN)->EnableWindow(false);//禁用提交按钮
//禁用导航按钮控件
GetDlgItem(IDC_FIRST)->EnableWindow(false);//禁用第一条按钮
GetDlgItem(IDC_NEXT)->EnableWindow(false);//禁用下一条按钮
GetDlgItem(IDC_PREV)->EnableWindow(false);//禁用上一条按钮
GetDlgItem(IDC_LAST)->EnableWindow(false);//禁用最后一条按钮
m_StuNo=m_StuName=m_StuAddress=m_StuTel="";
UpdateData(false);
}
void CCh15Demo1Dlg::OnRadio2()
{
// TODO: Add your control notification handler code here
m_radio=1;
GetDlgItem(IDC_ADD)->EnableWindow(false);//禁用添加按钮
GetDlgItem(IDC_REMOVE)->EnableWindow(true);//激活删除按钮
GetDlgItem(IDC_CHECKIN)->EnableWindow(false);//禁用提交按钮
//激活导航按钮控件
GetDlgItem(IDC_FIRST)->EnableWindow(true);//激活第一条按钮
GetDlgItem(IDC_NEXT)->EnableWindow(true);//激活下一条按钮
GetDlgItem(IDC_PREV)->EnableWindow(true);//激活上一条按钮
GetDlgItem(IDC_LAST)->EnableWindow(true);//激活最后一条按钮
_variant_t RecordsAffected;
m_pRecordset =m_pConnection->Execute("SELECT COUNT(*) FROM studentinfo",&RecordsAffected,adCmdText);
//&RecordsAffected是执行命令后的返回值,表明符合命令的的行数,可选参数
//adCmdTex指明执行命令的类型,可选参数
_variant_t vIndex = (long)0;
_variant_t vCount = m_pRecordset->GetCollect(vIndex); //取得第一个字段的值放入vCount变量
count=vCount.lVal;//获取记录集的
m_pRecordset->Close();///关闭记录集
if(count==0)//记录为0
{
GetDlgItem(IDC_REMOVE)->EnableWindow(false);//禁用删除按钮
//禁用导航按钮控件
GetDlgItem(IDC_FIRST)->EnableWindow(false);//禁用第一条按钮
GetDlgItem(IDC_NEXT)->EnableWindow(false);//禁用下一条按钮
GetDlgItem(IDC_PREV)->EnableWindow(false);//禁用上一条按钮
GetDlgItem(IDC_LAST)->EnableWindow(false);//禁用最后一条按钮
m_Status="表中没有数据!";
UpdateData(false);
return;
}
m_(__uuidof(Recordset));//创建记录集对象
CString strSQL="SELECT * FROM studentinfo";
try
{
//从数据库中打开表
m_pRecordset->Open(_bstr_t(strSQL), m_(),adOpenDynamic,adLockOptimistic,adCmdText);
}
catch (_com_error e)
{
CString strError;
("警告:打开数据表时发生异常。错误信息:%s",e.ErrorMessage());
AfxMessageBox(strError);
return;
}
m_pRecordset->MoveFirst();//移到第一条记录
curNo=1;
m_S("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
}
void CCh15Demo1Dlg::OnRadio3()
{
// TODO: Add your control notification handler code here
m_radio=2;
GetDlgItem(IDC_ADD)->EnableWindow(false);//禁用添加按钮
GetDlgItem(IDC_REMOVE)->EnableWindow(false);//禁用删除按钮
GetDlgItem(IDC_CHECKIN)->EnableWindow(true);//激活提交按钮
//激活导航按钮控件
GetDlgItem(IDC_FIRST)->EnableWindow(true);//激活第一条按钮
GetDlgItem(IDC_NEXT)->EnableWindow(true);//激活下一条按钮
GetDlgItem(IDC_PREV)->EnableWindow(true);//激活上一条按钮
GetDlgItem(IDC_LAST)->EnableWindow(true);//激活最后一条按钮
_variant_t RecordsAffected;
m_pRecordset =m_pConnection->Execute("SELECT COUNT(*) FROM studentinfo",&RecordsAffected,adCmdText);
_variant_t vIndex = (long)0;
_variant_t vCount = m_pRecordset->GetCollect(vIndex); //取得第一个字段的值放入vCount变量
count=vCount.lVal;
m_pRecordset->Close();///关闭记录集
if(count==0)//记录为0
{
GetDlgItem(IDC_CHECKIN)->EnableWindow(false);//禁用提交按钮
//禁用导航按钮控件
GetDlgItem(IDC_FIRST)->EnableWindow(false);//禁用第一条按钮
GetDlgItem(IDC_NEXT)->EnableWindow(false);//禁用下一条按钮
GetDlgItem(IDC_PREV)->EnableWindow(false);//禁用上一条按钮
GetDlgItem(IDC_LAST)->EnableWindow(false);//禁用最后一条按钮
return;
}
m_(__uuidof(Recordset));
CString strSQL="SELECT * FROM studentinfo";
try
{
//从数据库中打开表
m_pRecordset->Open(_bstr_t(strSQL), m_(),adOpenDynamic,adLockOptimistic,adCmdText);
}
catch (_com_error e)
{
CString strError;
("警告:打开数据表时发生异常。 错误信息: %s",e.ErrorMessage());
AfxMessageBox(strError);
return;
}
m_pRecordset->MoveFirst();//移到第一条记录
curNo=1;
m_S("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
}
void CCh15Demo1Dlg::OnAdd()
{
// TODO: Add your control notification handler code here
_variant_t RecordsAffected;
UpdateData();
i())
{
AfxMessageBox("学号不能为空!");
return;
}
CString strSQL;
("INSERT INTO studentinfo(stuNo,stuname,stuaddress,stuphone) VALUES ('%s', '%s','%s','%s')",m_StuNo,m_StuName,m_StuAddress,m_StuTel);
m_pConnection->Execute((_bstr_t)strSQL,&RecordsAffected,adCmdText);
m_Status="成功添加了一行记录!";
m_StuNo=m_StuName=m_StuAddress=m_StuTel="";
UpdateData(false);
}
//因为COM必须设计成跨平台,所以它需要一种更普遍的方式来处理字符串以及其他数据。在ADO技术实现对数据库的操作时,数据库中保存的都是COM类型的变量,其特有的数据类型为VARIANT和BSTR类型
//_variant_t类封装和管理Variant数据类型,在使用ADO对象模型操作数据库时,如果对象的方法或者属性接受某个值,则声明该值的形式为_variant_t,而非一般CString,二者可以强制转换
void CCh15Demo1Dlg::OnCheckin()
{
// TODO: Add your control notification handler code here
UpdateData();
m_pRecordset->PutCollect("stuNo",_variant_t(m_StuNo));
m_pRecordset->PutCollect("stuname",_variant_t(m_StuName));
m_pRecordset->PutCollect("stuaddress",_variant_t(m_StuAddress));
m_pRecordset->PutCollect("stuphone",_variant_t(m_StuTel));
m_pRecordset->Update();//提交记录
m_Status="成功修改了一条记录!";
UpdateData(false);
}
void CCh15Demo1Dlg::OnRemove()
{
// TODO: Add your control notification handler code here
m_pRecordset->Delete(adAffectCurrent);
m_Status="成功删除了一行记录!";
count=count-1;
UpdateData(false);
OnFirst();
}
//当得到记录集时,需要从各条记录中读出数据,必须在记录集中移动光标,使要访问的记录成为当前记录。ADO的记录集对象中提供了几种在记录集中移动记录指针的方法(函数),使用这些方法可以方便地得到要访问的记录。
void CCh15Demo1Dlg::OnFirst()
{
// TODO: Add your control notification handler code here
if(count==0)//记录为0
{
m_StuNo=m_StuName=m_StuAddress=m_StuTel="";
UpdateData(false);
GetDlgItem(IDC_REMOVE)->EnableWindow(false);//禁用删除按钮
//禁用导航按钮控件
GetDlgItem(IDC_FIRST)->EnableWindow(false);//禁用第一条按钮
GetDlgItem(IDC_NEXT)->EnableWindow(false);//禁用下一条按钮
GetDlgItem(IDC_PREV)->EnableWindow(false);//禁用上一条按钮
GetDlgItem(IDC_LAST)->EnableWindow(false);//禁用最后一条按钮
return;
}
m_pRecordset->MoveFirst();//移到第一条记录
curNo=1;
m_S("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
}
void CCh15Demo1Dlg::OnLast()
{
// TODO: Add your control notification handler code here
m_pRecordset->MoveLast();//移到最后一条记录
curNo=count;
m_S("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
}
void CCh15Demo1Dlg::OnNext()
{
// TODO: Add your control notification handler code here
if(curNo<count)
{
m_pRecordset->MoveNext();//移到下一条记录
curNo++;
if(m_pRecordset->adoEOF)
{
m_pRecordset->MoveLast();
}
m_S("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
}
}
void CCh15Demo1Dlg::OnPrev()
{
// TODO: Add your control notification handler code here
if(curNo>1)
{
m_pRecordset->MovePrevious();//移到上一条记录
curNo--;
if(m_pRecordset->BOF)
{
m_pRecordset->MoveFirst();
}
m_S("共有%d条记录,当前第%d条",count,curNo);
UpdateData(false);
ShowRecord();//显示记录
}
}
6 关闭记录集和连接
使用ClassWizard,重载对话框类WM_DESTROY消息响应函数DestroyWindow(),并添加如下代码:
BOOL CCh15Demo1Dlg::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
if(m_pRecordset!=NULL)
{
m_pRecordset->Close();//关闭记录集对象
m_pRecordset=NULL;
}
if(m_pConnection->State)
{
m_pConnection->Close();//关闭连接对象
m_pConnection=NULL;
}
return CDialog::DestroyWindow();
}
-End-