MFC - 数据库类

创建于 2024-12-03 / 34
字体: [默认] [大] [更大]

数据库是经过组织的信息集合,以便可以轻松访问、管理和更新。 基于 ODBC 的 MFC 数据库类旨在提供对任何可用 ODBC 驱动程序的数据库的访问。 由于这些类使用 ODBC,因此您的应用程序可以访问多种不同数据格式和不同本地/远程配置的数据。

您不必编写特殊情况的代码来处理不同的数据库管理系统 (DBMS)。 只要您的用户拥有适合他们想要访问的数据的 ODBC 驱动程序,他们就可以使用您的程序来操作存储在其中的表中的数据。 数据源是由某些数据库管理系统 (DBMS) 托管的数据的特定实例。 示例包括 Microsoft SQL Server、Microsoft Access 等。

CDatabase

MFC提供了一个类CDatabase,它代表与数据源的连接,通过它可以对数据源进行操作。 您可以在应用程序中同时使一个或多个 CDatabase 对象处于活动状态。

序号 名称和描述
1

BeginTrans

在连接的数据源上启动"事务",即对 CRecordset 类的 AddNew、Edit、Delete 和 Update 成员函数进行一系列可逆调用。 数据源必须支持事务,BeginTrans 才会生效。

2

BindParameters

允许您在调用ExecuteSQL之前绑定参数。

3

Cancel

从第二个线程取消异步操作或进程。

4

CanTransact

如果数据源支持事务,则返回非零。

5

CanUpdate

如果 CDatabase 对象可更新(非只读),则返回非零。

6

Close

关闭数据源连接。

7

CommitTrans

完成由 BeginTrans 开始的事务。 执行事务中更改数据源的命令。

8

ExecuteSQL

执行 SQL 语句。 没有返回任何数据记录。

9

GetBookmarkPersistence

标识书签在记录集对象上持久保存的操作。

10

GetConnect

返回用于将 CDatabase 对象连接到数据源的 ODBC 连接字符串。

11

GetCursorCommitBehavior

标识在打开的记录集对象上提交事务的效果。

12

GetCursorRollbackBehavior

标识回滚事务对打开的记录集对象的影响。

13

GetDatabaseName

返回当前使用的数据库的名称。

14

IsOpen

如果 CDatabase 对象当前连接到数据源,则返回非零。

15

OnSetOptions

由框架调用以设置标准连接选项。 默认实现设置查询超时值。 您可以通过调用SetQueryTimeout提前建立这些选项。

16

Open

建立与数据源的连接(通过 ODBC 驱动程序)。

17

OpenEx

建立与数据源的连接(通过 ODBC 驱动程序)。

18

Rollback

撤消当前事务期间所做的更改。 数据源返回到其之前的状态(如 BeginTrans 调用中所定义),未更改。

19

SetLoginTimeout

设置数据源连接尝试超时之前的秒数。

20

SetQueryTimeout

设置数据库查询操作超时后的秒数。 影响所有后续记录集 Open、AddNew、Edit 和 Delete 调用。

让我们通过创建一个新的基于 MFC 对话框的应用程序来研究一个简单的示例。

步骤 1 − 将 TODO 行的标题更改为从数据库检索数据,然后拖动一个按钮和一个列表控件,如下面的快照所示。

从数据库检索数据

步骤 2 − 添加按钮的点击事件处理程序和列表控件的控件变量m_ListControl。

步骤 3 − 我们有一个简单的数据库,其中包含一个雇员表和一些记录,如下面的快照所示。

员工表

步骤 4 − 我们需要包含以下头文件,以便我们可以使用 CDatabase 类。

#include "odbcinst.h"
#include "afxdb.h"

插入查询

SQL INSERT INTO 语句用于向数据库中的表添加新数据行。

步骤 1 − 要添加新记录,我们将使用 CDatabase 类的 ExecuteSQL() 函数,如以下代码所示。

CDatabase database;
CString SqlString;
CString strID, strName, strAge;
CString sDriver = L"MICROSOFT ACCESS DRIVER (*.mdb)";
CString sDsn;
CString sFile = L"D:\Test.mdb";
// You must change above path if it's different
int iRec = 0;

// Build ODBC connection string
sDsn.Format(L"ODBC;DRIVER={%s};DSN='';DBQ=%s", sDriver, sFile);
TRY {
   // Open the database
   database.Open(NULL,false,false,sDsn);

   SqlString = "INSERT INTO Employees (ID,Name,age) VALUES (5,'Sanjay',69)";
   database.ExecuteSQL(SqlString);
   // Close the database
   database.Close();
}CATCH(CDBException, e) {
   // If a database exception occured, show error msg
   AfxMessageBox(L"Database error: " + e→m_strError);
}
END_CATCH;

步骤 2 − 编译并执行上述代码后,您将看到数据库中添加了一条新记录。

插入队列

检索记录

为了在 MFC 应用程序中检索上表,我们在按钮事件处理程序中实现与数据库相关的操作,如以下步骤所示。

步骤 1 − 要使用 CDatabase,请构造一个 CDatabase 对象并调用其 Open() 函数。 这将打开连接。

步骤 2 − 构造 CRecordset 对象以在连接的数据源上进行操作,将记录集构造函数传递给 CDatabase 对象的指针。

步骤 3 − 使用连接后,调用Close函数并销毁CDatabase对象。

void CMFCDatabaseDemoDlg::OnBnClickedButtonRead() {
   // TODO: Add your control notification handler code here
   CDatabase database;
   CString SqlString;
   CString strID, strName, strAge;
   CString sDriver = "MICROSOFT ACCESS DRIVER (*.mdb)";
   CString sFile = L"D:\Test.mdb";
   // You must change above path if it's different
   int iRec = 0;

   // Build ODBC connection string
   sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,sFile);
   TRY {
      // Open the database
      database.Open(NULL,false,false,sDsn);

      // Allocate the recordset
      CRecordset recset( &database );

      // Build the SQL statement
      SqlString = "SELECT ID, Name, Age " "FROM Employees";

      // Execute the query
	  
      recset.Open(CRecordset::forwardOnly,SqlString,CRecordset::readOnly);
      // Reset List control if there is any data
      ResetListControl();
      // populate Grids
      ListView_SetExtendedListViewStyle(m_ListControl,LVS_EX_GRIDLINES);

      // Column width and heading
      m_ListControl.InsertColumn(0,"Emp ID",LVCFMT_LEFT,-1,0);
      m_ListControl.InsertColumn(1,"Name",LVCFMT_LEFT,-1,1);
      m_ListControl.InsertColumn(2, "Age", LVCFMT_LEFT, -1, 1);
      m_ListControl.SetColumnWidth(0, 120);
      m_ListControl.SetColumnWidth(1, 200);
      m_ListControl.SetColumnWidth(2, 200);

      // Loop through each record
      while( !recset.IsEOF() ) {
         // Copy each column into a variable
         recset.GetFieldValue("ID",strID);
         recset.GetFieldValue("Name",strName);
         recset.GetFieldValue("Age", strAge);

         // Insert values into the list control
         iRec = m_ListControl.InsertItem(0,strID,0);
         m_ListControl.SetItemText(0,1,strName);
         m_ListControl.SetItemText(0, 2, strAge);

         // goto next record
         recset.MoveNext();
      }
      // Close the database
      database.Close();
   }CATCH(CDBException, e) {
      // If a database exception occured, show error msg
      AfxMessageBox("Database error: "+e→m_strError);
   }
   END_CATCH; 
}

// Reset List control
void CMFCDatabaseDemoDlg::ResetListControl() {
   m_ListControl.DeleteAllItems();
   int iNbrOfColumns;
   CHeaderCtrl* pHeader = (CHeaderCtrl*)m_ListControl.GetDlgItem(0);
   if (pHeader) {
      iNbrOfColumns = pHeader→GetItemCount();
   }
   for (int i = iNbrOfColumns; i >= 0; i--) {
      m_ListControl.DeleteColumn(i);
   }
}

步骤 4 − 这是头文件。

// MFCDatabaseDemoDlg.h : header file
//

#pragma once
#include "afxcmn.h"


// CMFCDatabaseDemoDlg dialog
class CMFCDatabaseDemoDlg : public CDialogEx {
   // Construction
   public:
      CMFCDatabaseDemoDlg(CWnd* pParent = NULL);    // standard constructor

   // Dialog Data
   #ifdef AFX_DESIGN_TIME
      enum { IDD = IDD_MFCDATABASEDEMO_DIALOG };
   #endif

   protected:
      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
      void ResetListControl();

   // Implementation
   protected:
      HICON m_hIcon;

      // Generated message map functions
      virtual BOOL OnInitDialog();
      afx_msg void OnPaint();
      afx_msg HCURSOR OnQueryDragIcon();
      DECLARE_MESSAGE_MAP()
   public:
      CListCtrl m_ListControl;
      afx_msg void OnBnClickedButtonRead();
};

步骤 5 − 当上面的代码被编译并执行时,您将看到以下输出。

检索记录

步骤 6 − 按"读取"按钮执行数据库操作。 它将检索员工表。

检索记录

更新记录

SQL UPDATE 查询用于修改表中的现有记录。 您可以将 WHERE 子句与 UPDATE 查询一起使用来更新选定的行,否则所有行都会受到影响。

步骤 1 − 让我们看一个简单的例子,更新 ID 等于 5 的 Age。

SqlString = L"UPDATE Employees SET Age = 59 WHERE ID = 5;";
database.ExecuteSQL(SqlString);

步骤 2 − Here is the complete code of button click event.

void CMFCDatabaseDemoDlg::OnBnClickedButtonRead() {
   // TODO: Add your control notification handler code here
   CDatabase database;
   CString SqlString;
   CString strID, strName, strAge;
   CString sDriver = L"MICROSOFT ACCESS DRIVER (*.mdb)";
   CString sDsn;
   CString sFile =
      L"C:\Users\Muhammad.Waqas\Downloads\Compressed\ReadDB_demo\Test.mdb";
   // You must change above path if it's different
   int iRec = 0;

   // Build ODBC connection string
   sDsn.Format(L"ODBC;DRIVER={%s};DSN='';DBQ=%s", sDriver, sFile);
   TRY {
      // Open the database
      database.Open(NULL,false,false,sDsn);

      // Allocate the recordset
      CRecordset recset(&database);

      SqlString = L"UPDATE Employees SET Age = 59 WHERE ID = 5;";

      database.ExecuteSQL(SqlString);

      SqlString = "SELECT ID, Name, Age FROM Employees";

      // Build the SQL statement
      SqlString = "SELECT ID, Name, Age FROM Employees";

      // Execute the query
      recset.Open(CRecordset::forwardOnly,SqlString,CRecordset::readOnly);

      // Reset List control if there is any data
      ResetListControl();
      // populate Grids
      ListView_SetExtendedListViewStyle(m_listCtrl,LVS_EX_GRIDLINES);

      // Column width and heading
      m_listCtrl.InsertColumn(0,L"Emp ID",LVCFMT_LEFT,-1,0);
      m_listCtrl.InsertColumn(1,L"Name",LVCFMT_LEFT,-1,1);
      m_listCtrl.InsertColumn(2, L"Age", LVCFMT_LEFT, -1, 1);
      m_listCtrl.SetColumnWidth(0, 120);
      m_listCtrl.SetColumnWidth(1, 200);
      m_listCtrl.SetColumnWidth(2, 200);

      // Loop through each record
      while (!recset.IsEOF()) {
         // Copy each column into a variable
         recset.GetFieldValue(L"ID",strID);
         recset.GetFieldValue(L"Name",strName);
         recset.GetFieldValue(L"Age", strAge);

         // Insert values into the list control
         iRec = m_listCtrl.InsertItem(0,strID,0);
         m_listCtrl.SetItemText(0,1,strName);
         m_listCtrl.SetItemText(0, 2, strAge);

         // goto next record
         recset.MoveNext();
      }

      // Close the database
      database.Close();
   }CATCH(CDBException, e) {
      // If a database exception occured, show error msg
      AfxMessageBox(L"Database error: " + e→m_strError);
   }
   END_CATCH;
}

步骤 3 − 当上面的代码被编译并执行时,您将看到以下输出。

检索记录

步骤 4 − 按"读取"按钮执行数据库操作。 它将检索以下员工表。

更新记录

步骤 5 − 您现在可以看到年龄从 69 更新为 59。

删除记录

SQL DELETE 查询用于从表中删除现有记录。 您可以将 WHERE 子句与 DELETE 查询一起使用来删除选定的行,否则所有记录将被删除。

步骤 1 − 让我们看一个简单的例子,删除 ID 等于 3 的记录。

SqlString = L"DELETE FROM Employees WHERE ID = 3;";

database.ExecuteSQL(SqlString);

步骤 2 − Here is the complete code of button click event.

void CMFCDatabaseDemoDlg::OnBnClickedButtonRead() {
   // TODO: Add your control notification handler code here
   CDatabase database;
   CString SqlString;
   CString strID, strName, strAge;
   CString sDriver = L"MICROSOFT ACCESS DRIVER (*.mdb)";
   CString sDsn;
   CString sFile =
       L"C:\Users\Muhammad.Waqas\Downloads\Compressed\ReadDB_demo\Test.mdb";

   // You must change above path if it's different
   int iRec = 0;

   // Build ODBC connection string
   sDsn.Format(L"ODBC;DRIVER={%s};DSN='';DBQ=%s", sDriver, sFile);
   TRY {
      // Open the database
      database.Open(NULL,false,false,sDsn);

      // Allocate the recordset
      CRecordset recset(&database);

      SqlString = L"DELETE FROM Employees WHERE ID = 3;";

      database.ExecuteSQL(SqlString);

      SqlString = "SELECT ID, Name, Age FROM Employees";

      // Build the SQL statement
      SqlString = "SELECT ID, Name, Age FROM Employees";

      // Execute the query
      recset.Open(CRecordset::forwardOnly,SqlString,CRecordset::readOnly);

      // Reset List control if there is any data
      ResetListControl();
      // populate Grids
      ListView_SetExtendedListViewStyle(m_listCtrl,LVS_EX_GRIDLINES);
      // Column width and heading
      m_listCtrl.InsertColumn(0,L"Emp ID",LVCFMT_LEFT,-1,0);
      m_listCtrl.InsertColumn(1,L"Name",LVCFMT_LEFT,-1,1);
      m_listCtrl.InsertColumn(2, L"Age", LVCFMT_LEFT, -1, 1);
      m_listCtrl.SetColumnWidth(0, 120);
      m_listCtrl.SetColumnWidth(1, 200);
      m_listCtrl.SetColumnWidth(2, 200);

      // Loop through each record
      while (!recset.IsEOF()) {
         // Copy each column into a variable
         recset.GetFieldValue(L"ID",strID);
         recset.GetFieldValue(L"Name",strName);
         recset.GetFieldValue(L"Age", strAge);

         // Insert values into the list control
         iRec = m_listCtrl.InsertItem(0,strID,0);
         m_listCtrl.SetItemText(0,1,strName);
         m_listCtrl.SetItemText(0, 2, strAge);

         // goto next record
         recset.MoveNext();
      }
      // Close the database
      database.Close();
   }CATCH(CDBException, e) {
      // If a database exception occured, show error msg
      AfxMessageBox(L"Database error: " + e→m_strError);
   }
   END_CATCH;
}

步骤 3 − 当上面的代码被编译并执行时,您将看到以下输出。

检索记录

步骤 4 − 按"读取"按钮执行数据库操作。 它将检索员工表。

更新记录

0 人点赞过