零
ODBC:为客户编程软件提供了一种统一的接口。可用于处理不同数据库的客户应用程序。使用ODBC的应用程序可以与任何具有ODBC驱动程序的数据库进行通信。
DAO:数据库访问对象,是一组数据库引擎的COM自动化接口。不是ODBC那样面向C++程序员,而是提供给VisualBasic开发人员的一种简单的数据库访问方法,用于操纵Access数据库。
RDO:远程数据对象。通过直接调用ODBC API,可以为使用关系数据库的应用程序提供更好的性能。
一、准备工作
创建MFC文件,选择以下格式
此处有些版本的MFC是没有支持数据的部分,因此需要自己设置。
笔者使用的为MySQL数据库。
数据源:用来记录连接数据库的信息,在创建数据库连接时需要,之后使用中不再需要。一个数据库可以有多个数据源连接。
它可分为文件数据源和机器数据源。
- 文件数据源:可以拷贝给其他计算机用
- 机器数据源:只有本机可以使用。机器数据源又分为:
- 用户数据源:当前创建的用户可见
- 系统数据源:所有用户可见
它的更新模式分为快照和动态记录集两种。
- 快照记录集:每次操作重新查询后才更新
- 动态记录集:每次操作自动更新(添加记录除外)
笔者的版本没有数据源。因此直接手动导入数据库用的是Mysql自带的包,注意,需要去Oracle官网下载ODBC管理程序。因为MFC的CDatabase需要数据源格式文件。
并建立如下数据库。
现在打开ODBC管理程序。
注意不要开启错了
通过“控制面板”进入“管理工具”
打开64位的(所含内容不同)
现在在文档DSN标签下,添加文档DSN(数据源),并完成配置。如此便生成完毕。
二、MFCApplication1Set类
现为MFC新增一类,还原MFC同ODBC自动生成的结构。
命名方式为MFCApplication1Set.h与.cpp
在完成下列代码后,其实数据源便没用了。其主要作用就是辅助生成连接数据库的基本代码。
#pragma once
#include "afxdb.h"
class CMFCApplication1Set : public CRecordset {
public:
CMFCApplication1Set(CDatabase* pDatabase = NULL);
DECLARE_DYNAMIC(CMFCApplication1Set);
public:
//此处是我们的数据库字段/参数数据
int m_sno;
CString m_address;
CString m_sname;
// 重写
// 向导生成的虚函数重写
public:
virtual CString GetDefaultConnect(); // 默认连接字符串
virtual CString GetDefaultSQL(); // 记录集的默认 SQL
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX 支持
// 实现
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
};
#include "pch.h"
#include "MFCApplication1Set.h"
IMPLEMENT_DYNAMIC(CMFCApplication1Set, CRecordset)
CMFCApplication1Set::CMFCApplication1Set(CDatabase* pDatabase)
:CRecordset(pDatabase)
{
m_sno = 0;
m_sname = L"";
m_address = L"";
m_nFields = 3;//数据域数目
m_nDefaultType = snapshot;//快照模式
}
#ifdef _DEBUG
void CMFCApplication1Set::AssertValid() const
{
CRecordset::AssertValid();
}
void CMFCApplication1Set::Dump(CDumpContext& dc) const
{
CRecordset::Dump(dc);
}
#endif //_DEBUG
void CMFCApplication1Set::DoFieldExchange(CFieldExchange* pFX)
{
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Int(pFX, _T("[sno]"), m_sno);
RFX_Text(pFX, _T("[sname]"), m_sname);
RFX_Text(pFX, _T("[address]"), m_address);
}
CString CMFCApplication1Set::GetDefaultConnect()
{
//数据源中信息
return _T("Driver=MySQL ODBC 8.0 Unicode Driver;SERVER=127.0.0.1;UID=用户;PWD=密码;DATABASE=数据库名;PORT=端口号(3360)");
}
CString CMFCApplication1Set::GetDefaultSQL()
{
return _T("[students]");
}
三、窗口布局
建立如下布局
为编辑框右击添加值变量
自动生成如下代码:
同时要初始化m_sno
四、数据库类
在DOC类的头文件中添加CMFCApplication1Set的头文件,而后添加成员变量以及方法。
// 特性
public:
CMFCApplication1Set* GetSet() {
return &pSet;
}
private:
CMFCApplication1Set pSet;//数据库记录集对象
然后在View的中修改如下
void CMFCApplication1View::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
//初始化时,把数据库打开
//文档对象指针
CMFCApplication1Doc* pDoc = GetDocument();
//数据库记录集指针
pSet = pDoc->GetSet();
if (pSet->IsOpen() == FALSE) {//数据库未开启,则打开
pSet->Open();
}
if (pSet->IsEOF()) {
m_sno = 0;
}
else {
//初始化内容
pSet->MoveFirst();
m_sno = pSet->m_sno;
m_sname = pSet->m_sname;
m_address = pSet->m_address;
}
UpdateData(FALSE);
}
五、添加事件
为“上一个”、“下一个”添加点击事件
(pSet->requery()可以重置查询)
//上一个
void CMFCApplication1View::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
if (pSet->IsEOF()) {
return;
}
pSet->MovePrev();
//如果是开始的第一个
if (pSet->IsBOF()) {
//变为最后一个
pSet->MoveLast();
}
m_sno = pSet->m_sno;
m_sname = pSet->m_sname;
m_address = pSet->m_address;
UpdateData(FALSE);
}
//下一个
void CMFCApplication1View::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
if (pSet->IsEOF()) {
return;
}
pSet->MoveNext();
if (pSet->IsEOF()) {
pSet->MoveFirst();
}
m_sno = pSet->m_sno;
m_sname = pSet->m_sname;
m_address = pSet->m_address;
UpdateData(FALSE);
}
为“添加记录”以及“确认”按钮添加点击事件
//添加记录
void CMFCApplication1View::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
//数据库添加空记录
pSet->AddNew();
}
//确定添加记录
void CMFCApplication1View::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
pSet->m_sno =m_sno;
pSet->m_sname = m_sname;
pSet->m_address = m_address;
//更新到数据库
if (pSet->CanUpdate()) {
pSet->Update();
}
}
为“修改”按钮添加点击事件
//修改
void CMFCApplication1View::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
pSet->Edit();
UpdateData(TRUE);
pSet->m_sno = m_sno;
pSet->m_sname = m_sname;
pSet->m_address = m_address;
//更新到数据库
if (pSet->CanUpdate()) {
pSet->Update();
}
}
为”删除“按钮添加点击事件
//删除
void CMFCApplication1View::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
//删除
pSet->Delete();
//重新查询
pSet->Requery();
if (pSet->IsEOF()) {
m_sno = 0;
m_sname.Empty();
m_address.Empty();
}
else {
m_sno = pSet->m_sno;
m_sname = pSet->m_sname;
m_address = pSet->m_address;
}
UpdateData(FALSE);
}
为”学号大于3“按钮添加 点击事件
//查询
void CMFCApplication1View::OnBnClickedButton8()
{
// TODO: 在此添加控件通知处理程序代码
pSet->m_strFilter = TEXT("sno > 3");
pSet->Requery();
if (pSet->IsEOF()) {
m_sno = 0;
m_sname.Empty();
m_address.Empty();
}
else {
m_sno = pSet->m_sno;
m_sname = pSet->m_sname;
m_address = pSet->m_address;
}
UpdateData(FALSE);
}
为”学号降序“按钮添加点击事件
void CMFCApplication1View::OnBnClickedButton6()
{
// TODO: 在此添加控件通知处理程序代码
//默认升序
pSet->m_strSort = TEXT("sno desc");
pSet->Requery();
if (pSet->IsEOF()) {
m_sno = 0;
m_sname.Empty();
m_address.Empty();
}
else {
m_sno = pSet->m_sno;
m_sname = pSet->m_sname;
m_address = pSet->m_address;
}
UpdateData(FALSE);
}
为”取消条件“按钮添加点击事件
//取消条件
void CMFCApplication1View::OnBnClickedButton9()
{
// TODO: 在此添加控件通知处理程序代码
pSet->m_strFilter = TEXT("");
pSet->m_strSort = TEXT("");
pSet->Requery();
if (pSet->IsEOF()) {
m_sno = 0;
m_sname.Empty();
m_address.Empty();
}
else {
m_sno = pSet->m_sno;
m_sname = pSet->m_sname;
m_address = pSet->m_address;
}
UpdateData(FALSE);
}
结果: