[MFC] Database operation - ODBC (20)

ODBC: Open Database Connection, which was created to solve the sharing of heterogeneous databases (different databases use different data storage methods). ODBC API is relatively very complicated, here is the ODBC class of MFC.

Add ODBC user DSN

First, add a user DSN to the computer: (under WIN10, search for ODBC)

 Click Add, take SQL Server as an example, others are similar (MYSQL needs to install the corresponding ODBC driver):

 Fill in the DSN name, description, IP address (this machine uses 127.0.0.1)

 Log in as a Windows user on this machine, and other computers can log in with username + password:

 Select the corresponding database (be careful!)

 After clicking Finish, test the data source:

The user DSN appears in ODBC, indicating that the addition is successful.

Using the MFC ODBC classes

Create Project-"Single Document-" In the database support step, select the database:

 Click on the data source and select the test added above:

 After clicking OK, select a table in the database (only one table can be selected):

 After clicking OK, the project is created, open the resource view, and add some controls in the main view to display the data in the database:

 Note that the control corresponds to the table in the database: (the example shows four columns in the database table)

Modify the view code to directly complete the binding between the control and the database column:

Respond to the four commands in the toolbar in the view class:

 code show as below:

 Run the program to see the data in the database (there is a security warning, just delete the code)

Add sorting and searching functions:

By setting the sorting field m_strSort of RecordSet and re-querying the database, sorting by this keyword can be completed

By setting the sorting field m_strFilter of RecordSet, the database can be searched according to this field (actually it is the where clause)

code show as below:

View header file:


// MFC10View.h : CMFC10View 类的接口
//

#pragma once

class CMFC10Set;

class CMFC10View : public CRecordView
{
protected: // 仅从序列化创建
	CMFC10View();
	DECLARE_DYNCREATE(CMFC10View)

public:
	enum{ IDD = IDD_MFC10_FORM };
	CMFC10Set* m_pSet;

// 特性
public:
	CMFC10Doc* GetDocument() const;

// 操作
public:

// 重写
public:
	virtual CRecordset* OnGetRecordset();
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
	virtual void OnInitialUpdate(); // 构造后第一次调用
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// 实现
public:
	virtual ~CMFC10View();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// 生成的消息映射函数
protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnRecordFirst();
	afx_msg void OnRecordLast();
	afx_msg void OnRecordNext();
	afx_msg void OnRecordPrev();
	afx_msg void OnBnClickedButton1();
	afx_msg void OnClickedTagnames();
	CString m_strSel;
	CString m_filter;
	void Query();
	afx_msg void OnBnClickedButton2();
};

#ifndef _DEBUG  // MFC10View.cpp 中的调试版本
inline CMFC10Doc* CMFC10View::GetDocument() const
   { return reinterpret_cast<CMFC10Doc*>(m_pDocument); }
#endif

CPP file


// MFC10View.cpp : CMFC10View 类的实现
//

#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "MFC10.h"
#endif

#include "MFC10Set.h"
#include "MFC10Doc.h"
#include "MFC10View.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include "resource.h"
#include "DevicesTable.h"
// CMFC10View

IMPLEMENT_DYNCREATE(CMFC10View, CRecordView)

BEGIN_MESSAGE_MAP(CMFC10View, CRecordView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CRecordView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CRecordView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CRecordView::OnFilePrintPreview)
	ON_COMMAND(ID_RECORD_FIRST, &CMFC10View::OnRecordFirst)
	ON_COMMAND(ID_RECORD_LAST, &CMFC10View::OnRecordLast)
	ON_COMMAND(ID_RECORD_NEXT, &CMFC10View::OnRecordNext)
	ON_COMMAND(ID_RECORD_PREV, &CMFC10View::OnRecordPrev)
	ON_BN_CLICKED(IDC_BUTTON1, &CMFC10View::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_TagNames, &CMFC10View::OnClickedTagnames)
	ON_BN_CLICKED(IDC_KKSCode, &CMFC10View::OnClickedTagnames)
	ON_BN_CLICKED(IDC_Descriptors, &CMFC10View::OnClickedTagnames)
	ON_BN_CLICKED(IDC_PointType, &CMFC10View::OnClickedTagnames)
	ON_BN_CLICKED(IDC_BUTTON2, &CMFC10View::OnBnClickedButton2)
END_MESSAGE_MAP()

// CMFC10View 构造/析构

CMFC10View::CMFC10View()
	: CRecordView(CMFC10View::IDD)
	, m_filter(_T(""))
{
	m_pSet = NULL;
	// TODO: 在此处添加构造代码

}

CMFC10View::~CMFC10View()
{
}

void CMFC10View::DoDataExchange(CDataExchange* pDX)
{
	CRecordView::DoDataExchange(pDX);
	// 可以在此处插入 DDX_Field* 函数以将控件“连接”到数据库字段,例如
	// DDX_FieldText(pDX, IDC_MYEDITBOX, m_pSet->m_szColumn1, m_pSet);
	// DDX_FieldCheck(pDX, IDC_MYCHECKBOX, m_pSet->m_bColumn2, m_pSet);
	// 有关详细信息,请参阅 MSDN 和 ODBC 示例
	DDX_FieldText(pDX, IDC_EDIT1, (CString)m_pSet->m_TagNames, m_pSet);
	DDX_FieldText(pDX, IDC_EDIT2, (CString)m_pSet->m_KKSCode, m_pSet);
	DDX_FieldText(pDX, IDC_EDIT3, (CString)m_pSet->m_Descriptors, m_pSet);
	DDX_FieldText(pDX, IDC_EDIT4, (CString)m_pSet->m_PointType, m_pSet);
	//  DDX_Radio(pDX, IDC_TagNames, m_select);
	DDX_Text(pDX, IDC_FILTER, m_filter);
}

BOOL CMFC10View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CRecordView::PreCreateWindow(cs);
}

void CMFC10View::OnInitialUpdate()
{
	m_pSet = &GetDocument()->m_MFC10Set;
	CheckRadioButton(IDC_TagNames,IDC_PointType,IDC_TagNames);
	m_strSel="TagNames";
	
	CRecordView::OnInitialUpdate();

}
void CMFC10View::Query()
{
	// 默认准备
	m_pSet->m_strSort=m_strSel;
	if(m_filter!="")
		m_pSet->m_strFilter=m_strSel+"="+m_filter;
	m_pSet->Requery();
	OnRecordFirst();
}

// CMFC10View 打印

BOOL CMFC10View::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void CMFC10View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void CMFC10View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// CMFC10View 诊断

#ifdef _DEBUG
void CMFC10View::AssertValid() const
{
	CRecordView::AssertValid();
}

void CMFC10View::Dump(CDumpContext& dc) const
{
	CRecordView::Dump(dc);
}

CMFC10Doc* CMFC10View::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFC10Doc)));
	return (CMFC10Doc*)m_pDocument;
}
#endif //_DEBUG


// CMFC10View 数据库支持
CRecordset* CMFC10View::OnGetRecordset()
{
	return m_pSet;
}



// CMFC10View 消息处理程序


void CMFC10View::OnRecordFirst()
{
	// TODO: 在此添加命令处理程序代码
	if(m_pSet->IsOpen())
	{
		m_pSet->MoveFirst();	
		this->UpdateData(false);
	}	
}
void CMFC10View::OnRecordLast()
{
	// TODO: 在此添加命令处理程序代码
	if(m_pSet->IsOpen())
	{
		m_pSet->MoveLast();
		this->UpdateData(false);
	}	
}
void CMFC10View::OnRecordNext()
{
	// TODO: 在此添加命令处理程序代码
	if(m_pSet->IsOpen())
	{
		m_pSet->MoveNext();
		this->UpdateData(false);
	}
	
}


void CMFC10View::OnRecordPrev()
{
	// TODO: 在此添加命令处理程序代码
	if(m_pSet->IsOpen())
	{
		m_pSet->MovePrev();
		this->UpdateData(false);
	}
	
}


void CMFC10View::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	
	Query();
}


void CMFC10View::OnClickedTagnames()
{
	// TODO: 在此添加控件通知处理程序代码
	if(IsDlgButtonChecked(IDC_TagNames))
		m_strSel="TagNames";

	if(IsDlgButtonChecked(IDC_KKSCode))
		m_strSel="KKSCode";
	if(IsDlgButtonChecked(IDC_Descriptors))
		m_strSel="Descriptors";
	if(IsDlgButtonChecked(IDC_PointType))
		m_strSel="PointType";

	
}



void CMFC10View::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	
	Query();
}

in conclusion:

1. MFC ODBC is relatively simple to use, and it is easy to complete the generation of database classes. The bundled data table is a derived class of CRecordSet (automatically generated), and embedded in the document class:

The operation on the specified table in the database is done through this object (addition, deletion, query and modification). In the example, the view obtains the recordset object by obtaining the document class pointer:

 2. When MFC ODBC creates a project, only one table can be added to generate the corresponding record set class (selecting multiple tables will merge into one class, which is obviously wrong). If you need to operate on multiple tables in the database, you can choose to add the ODBC class through the class wizard:

 Note that when using it, you need to open it first:

	CDevicesTable devSet; //新增的另外一张表
	devSet.Open();
	devSet.Requery();
	devSet.MoveFirst();

3. You can use tables to generate corresponding collection classes, or you can use views to generate them (to solve cross-table queries such as left and right joins, etc.);

4. You can use the code to dynamically generate a DSN (otherwise you need to manually create a DSN to run the program on other computers);

5. Obviously, MFC ODBC is only suitable for relatively simple database operations, and it is not easy to implement complex database operations.

Guess you like

Origin blog.csdn.net/yixiaobo2001/article/details/129124605