当前位置:首页 > 问答 > 正文

MFC里怎么搞定数据库数据读取这事儿,简单说说步骤和注意点

要是在MFC这老伙计的地盘上整数据库数据读取这事儿,说白了就是几个固定的步骤,跟按菜谱炒菜差不多,你别被“数据库”仨字吓到,把它想象成一个装满数据的Excel表格文件,MFC就是帮你打开这个文件、然后一行行把数据读出来的工具,下面我就按最常用的ODBC方式来说道说道,这法子比较通用,对付Access、SQL Server啥的都行。

第一步:准备工作——把路修好

你想去数据库里取东西,总得先知道数据库在哪儿、怎么连上它吧?这一步就是干这个的。

  1. 配数据源: 这是最关键的一步,你得在Windows系统里告诉电脑:“嗨,有个数据库在某某地方,以后我叫‘我的数据库’这个名字,你就去那里找。”这个操作不是在MFC里做的,而是去Windows的“控制面板”里,找到“管理工具”,里面的“ODBC 数据源”(有的是32位和64位之分,得选对),进去之后,添加一个“用户DSN”或者“系统DSN”,然后选择你数据库对应的驱动程序(比如Access用Microsoft Access Driver,SQL Server就用它的那个),接着会弹出一个框让你设置,主要就是给你这个数据源起个名(这个名后面编程要用到),然后选择数据库文件的具体路径,这一步相当于给数据库安装了一个门牌号,MFC程序只要喊这个门牌号就能找到门了。(来源:MFC技术文档中关于CDatabase类初始化的前提条件说明)

第二步:在MFC项目里开干——牵线搭桥

路修好了,现在要在你的MFC程序里把这条线接上。

  1. 连上数据库: 在你的程序代码里,比如某个按钮的点击事件里,你需要用一个叫 CDatabase 的类,这个类就是专门负责管理数据库连接的,用起来很简单,先定义一个 CDatabase 对象,比如叫 m_db,然后调用它的 OpenEx 函数,参数就填你刚才在ODBC里设置的那个数据源的名字,代码大概长这样:m_db.OpenEx(_T("DSN=你起的数据源名字”));,如果连接成功,这个 m_db 对象就和数据库搭上线了,用完数据库之后,要记得调用 Close() 方法把连接关掉,不然占着资源不好。(来源:MSDN库中CDatabase::OpenEx方法文档)

  2. 拉取数据: 光连上还不行,你得把数据拿出来,这就要用到另一个重要的类 CRecordset,这个类代表从数据库里查出来的一组记录(就是那个Excel表格里的几行数据),你通常需要自己创建一个从 CRecordset 继承过来的新类,用MFC的类向导就能轻松搞定,向导会让你选择刚才连上的那个数据源,然后让你选数据库里的哪张表(就是哪个Sheet页),接着它会自动把表里的字段(就是列头)变成你这个新类的成员变量,这样,你程序里的变量就和数据库表的列一一对应了。

第三步:操作数据——怎么读和要注意啥

线也搭好了,工具也准备好了,现在可以动手读了。

  1. 执行查询和遍历: 在你刚创建的记录集类里,有个 Open 函数,你调用它,它就会真的去数据库里执行查询,把数据抓回来,默认是抓回整张表的所有数据,你也可以在调用 Open 之前设置一个SQL语句字符串,只抓你想要的,数据抓回来后,就像有个指针指着第一行数据,你可以用 IsEOF() 函数判断是不是读到尾巴了,没到尾巴,你就可以通过那些自动生成的成员变量来读取当前行各个列的值,读完一行,调用 MoveNext() 跳到下一行,直到 IsEOF() 告诉你读完了。(来源:MSDN库中CRecordset类成员函数如Open、IsEOF、MoveNext的说明)

几个要命的注意点,搞不好就掉坑里:

  • 字符编码的老大难问题: 这是MFC搞数据库最容易出幺蛾子的地方,特别是现在普遍用Unicode编码,但有些老数据库还是多字节的,如果你发现读出来的中文是乱码,十有八九是这儿的问题,解决办法通常是在连接字符串(就是那个 OpenEx 的参数)里加上一段像 "Charset=UTF8" 这样的设置(具体加什么看你的数据库编码),或者确保你的程序编译时选择的字符集(Unicode还是多字节)和你的数据库匹配,这块儿需要试,没统一答案。
  • 别忘关和异常处理: 就像你开了水龙头要记得关一样,打开了数据库连接 (CDatabase::OpenEx) 和记录集 (CRecordset::Open),用完之后一定要调用对应的 Close() 方法,而且这些操作最好放在 try...catch 语句块里,因为网络波动、数据库服务挂了都可能导致连接失败,不加异常处理程序直接就崩了。
  • 记录集对象的状态: 那个 CRecordset 对象在你调用 AddNew(准备新增)或 Edit(准备编辑)之后,会处于一个“脏”的状态,这时候如果你直接 MoveNext 或者 Close,可能会丢失修改,所以操作要小心,确认了更新 (Update) 或者取消操作之后再进行下一步。
  • SQL注入风险: 如果你不是直接读全表,而是自己拼接SQL语句("SELECT * FROM table WHERE name = '" + strName + "'")来查询,那就要非常小心“SQL注入”攻击,如果用户输入的 strName 里面包含一些特殊的SQL字符,就可能篡改你的查询逻辑,非常危险,简单的防范办法是用参数化查询,CRecordset 是支持这个功能的,别图省事自己拼字符串。

在MFC里读数据库,核心就是 CDatabase 管连接,CRecordset 管取数据,步骤固定,但细节坑多,特别是编码和资源管理,多试几次,遇到问题搜一下具体的错误提示,基本都能解决。

MFC里怎么搞定数据库数据读取这事儿,简单说说步骤和注意点