MFC下的ODBC数据库及其优化

来源:互联网 发布:网络教育专科有必要 编辑:程序博客网 时间:2024/04/29 18:23

 

编者按:本文改编自MSDN,原作者Jocelyn Garner,原文写作时间象青铜器那么远,因为我基本google不到它给出的几篇参考文献。原文还涉及了许多DAO的知识,而我只关心ODBC,于是就改编了一下这篇古文。另一个原因在于MFC中的ODBC类在VC6以后就没有大的改动(似乎?),原文提出的方法仍然很有指导作用,相信详细阅读本文,你还是会有很多收获。(ROY LEE

 

 

MFC下的ODBC数据库及其优化... 1

MFC ODBC 数据库类... 1

ODBC 数据库类的数据源选择... 2

优化您的 MFC 数据库应用程序... 3

优化 ODBC 数据库和记录集对象... 3

优化基于 ODBC 的数据库交互... 5

其它用于优化应用程序的资源... 5

 

 

 

MFC ODBC 数据库类

就象使用 MFC 那样,必要时可以调用基础 API(在此情况下为 ODBC)。

一个 CDatabase 对象代表一个到数据源的连接,通过此连接您可以在数据源上进行操作。数据源是指以某些数据库管理系统 (DBMS) 作为宿主的指定数据实例。具体示例包括 Microsoft SQL ServerMicrosoft AccessBorland dBASE xBASE。您可以在自己的应用程序中同时让一个或多个 CDatabase 对象处于活动状态,并且可以保持到一个数据库对象的多个连接。

一个 CRecordset 对象代表从数据源中选择的一个记录集合。称为"记录集" CRecordset 对象有三种可用的形式:动态集、快照、动态记录集。动态集是与其他用户的更新保持同步的记录集。快照是静态记录集,它反映的是抓拍快照时数据库的状态。动态记录集类似于动态集,但通常只用于 Microsoft SQL Server。每种形式都代表在打开记录集时确定的记录集合,但当您在动态集内或动态记录集内滚动到一条记录时,它反映后来由其他用户或您应用程序中的其它记录集对记录所做的更改。

MFC 4.2 以书签的形式向 CRecordset 类中添加新的导航功能,并添加标识及导航到记录的 AbsolutePosition 的能力。书签是唯一的标识符,通过调用该标识符可返回指定的记录。

CRecordView 是一种 MFC 构造 - 一种显示数据的形式。因为 CRecordView 是基于 CFormView 的,所以它具有该基础类的所有遗传功能。从本质上说,窗体视图在窗口的客户端区域伸展对话框模板。这使得添加控件与显示字段数据极为容易。

当使用 AppWizard ClassWizard 创建基于 ODBC 的数据库应用程序时,记录集的列会自动绑定到(静态地)成员变量,这些变量可以随后添加到对话框模板中。

一个 CDBException 对象代表一种由数据库类引起的异常错误条件。该类中含有两个公共数据成员,可使用这两个成员确定导致异常错误的原因,或显示对异常错误进行说明的文本消息。CDBException 对象由数据库类的成员函数构造与抛出。

CFieldExchange 类支持由数据库类使用的记录字段交换 (RFX) 例程。如果您正在编写自定义数据类型的数据交换例程,则使用该类;否则,您不会直接使用该类。RFX 在您记录集对象的字段数据成员和数据源上当前记录的相应字段之间交换数据。RFX 管理两个方向中的交换,即来自数据源的交换与到数据源的交换。

1 MFC ODBC 数据库类

这里是基于 ODBC 的数据库类的图片,与您所了解的相同。顶端的栏代表基于 ODBC、与 ODBC 交谈的 MFC 类。每个数据库的 ODBC 驱动程序都解释 SQL 调用,并针对每个数据源对其进行转换。许多数据源都与相应的驱动程序一起显示在关系图的底部,以提醒您 ODBC 的灵活性。

ODBC 数据库类的数据源选择

当您用 MFC ODBC 类编写应用程序时,可以连接到任何数据源(只要您有它的 ODBC 驱动程序)。ODBC 驱动程序管理器和 ODBC 驱动程序的操作在您用这些类编写的应用程序中是透明的,但个别驱动程序性能会影响应用程序的功能。

通常,MFC 动态集(但并非只向前滚动的记录集)要求 ODBC 驱动程序具有 2 API 一致性。如果数据源的驱动程序符合 1 API 设置,您就仍可以使用可更新且只读的快照与只向前滚动的记录集,但不能使用动态集。然而,如果 1 级驱动程序支持扩展的提取和键集驱动游标,它就可以支持动态集。

ODBC Desktop Driver Pack 3.0 版支持 2 ODBC API 调用 SQLExtendedFetch

AppWizard ClassWizard 会自动将数据源的列静态地绑定到您应用程序的成员变量中。这是在您应用程序与数据源之间建立连接的最简单的方法,但不是最灵活的方法。可以用类 CFieldExchange 将自定义的记录字段交换 (RFX) 调用添加到您的应用程序中。请参见"Technical Note 43RFX Routines",以获取更多信息。

另外,还可以考虑动态地绑定数据库的列。在最普通的级别中可执行下列步骤:

构造您的主要记录集对象。然后,可以将指针传递给一个打开的 CDatabase 对象,或者也可以用其它方法向列记录集提供连接信息。

执行一些步骤,动态地添加列。

打开您的主要记录集。

记录集会选择记录,并使用记录字段交换 (RFX) 绑定"静态"列(映射到记录集字段数据成员的列)和动态列(映射到您分配的额外存储的列)。

ODBC 数据库类的其它功能

自从 MFC 4.2 开始,ODBC 数据库类就是多线程的。若要利用此性能,就必须使用多线程的 ODBC 驱动程序。DAO 正开发成单元线程,但尚未确定何时能投入使用。

MFC 4.2 中,大量行提取功能是新功能,另外还添加了特殊的导航能力。

在针对许多问题的解答中,我们已经对控制台数据库应用程序给予了更好的支持。

优化您的 MFC 数据库应用程序

有一些明显但常被忽略的方法可以改进应用程序的性能。例如,查明您的网络怎样才能增强或妨碍数据检索(如异步查询)。

您所拥有的 ODBC 驱动程序的类型可能也会影响网络的性能。

单级驱动程序用于那些不基于 SQL 的数据库。其数据库文件直接由该驱动程序处理。该驱动程序处理 SQL 语句并从数据库中检索信息。SQL 语句一经分析与转换后,就作为基本文件操作传给数据库。处理 xBASE 文件的驱动程序是执行单级驱动程序的一个示例。

单级驱动程序可能会限制可提交的 SQL 语句集合。单级驱动程序必须支持的最小 SQL 语句集合是在附录 C"SQL 语法"中的 ODBC SDK《程序员指南》中定义的。

单级驱动程序通常要比使用本机 DBMS 工具(如 Microsoft FoxPro)慢一些,因为它们要分析 SQL 语句分析并将其转换成基本文件操作。它们慢到什么程度取决于该进程的优化程度。两个不同单级驱动程序之间的速度差异通常要归因于优化的方法。

在多级配置中,驱动程序将请求发送到处理这些请求的服务器。请求采用的格式可能是 SQL DBMS 专用的格式。虽然整个安装可以在一个系统上完成,但更常见的则是分布到各个平台中。通常,应用程序、驱动程序和驱动程序管理器均驻留在一个系统上,称为客户端。而数据库和控制对数据库访问的软件则驻留在另一个系统上,称为服务器。有两种类型的多级驱动程序:两级和三级(或网关)。有关的详细信息,请参见 Colleen Lambert 的文章"ODBCArchitecturePerformanceand Tuning"(位于 Microsoft Developer Network 光盘)。

优化 ODBC 数据库和记录集对象

当您打开 CDatabase 对象时,就可以提供数据源名称或 NULL 以向用户显示选择对话框。MFC ODBC 数据库类不支持对数据库的排它性访问,因此连接总是共享的。但是,您可以以只读方式打开数据库。请记住,如果这样做,则所有从该 CDatabase 对象派生的记录集将也是只读的。下面的选项可使得控制台应用程序的编写更为容易。这些新选项是用户最常请求的。

CDatabase::noOdbcDialog 无论提供的连接信息是否足够,都不显示 ODBC 连接对话框。

CDatabase::forceOdbcDialog 总是显示 ODBC 连接对话框。

您可以选择将 ODBC 游标库与您的应用程序装载到一起。根据基础驱动程序的性能,您也可能不需要它。游标库可掩藏基础 ODBC 驱动程序的某些功能,从而有效地防止使用动态集(如果驱动程序支持它们)。如果装载了游标库,将只支持静态快照和"forwardOnly"游标。

所打开的 CRecordset 对象的类型将对应用程序性能有很大影响。如果您想让动态记录集实现双向滚动,请选择 CRecordset::dynaset 类型。若想让静态记录集实现双向滚动,请选择 CRecordset::snapshot 类型。如果不需要对数据进行来回滚动,请选择 CRecordset::forwardOnly 类型,这样会创建一个只能向前滚动的只读记录集。新的 CRecordset::dynamic 类型记录集是一个可双向滚动的记录集。在进行提取操作后,其他用户对成员身份、排序以及数据值所做的更改都是可见的。但是请注意,许多 ODBC 驱动程序不支持这种类型的记录集。

CRecordset 的其它选项有:

CRecordset::none 未设置任何选项。默认情况下,可以用 Edit Delete 对记录集进行更新,而且允许用 AddNew 追加新记录。可更新性不仅取决于数据源,也取决于您指定的选项。

CRecordset::appendOnly 不允许在记录集上进行 Edit Delete 操作。只允许使用 AddNew

CRecordset::readOnly 以只读方式打开记录集。

CRecordset::optimizeBulkAdd 使用已准备好的 SQL 语句,一次优化添加多个记录的操作。该选项与 CRecordset::useMultiRowFetch 是互斥的。

CRecordset::useMultiRowFetch 执行大量行提取,以允许在一个提取操作中检索多行。该选项与 CRecordset::optimizeBulkAdd 是互斥的。请注意,如果指定 CRecordset::useMultiRowFetch,则会自动开启选项 CRecordset::noDirtyFieldCheck(双缓冲将不可用);在只向前滚动记录集上,将自动开启选项 CRecordset::useExtendedFetch

CRecordset::skipDeletedRecords 在记录集内导航时跳过已删除的记录。这会降低某些相关提取的性能。该选项在只向前滚动记录集上无效。请注意,CRecordset::skipDeletedRecords "驱动程序包装"类似,这意味着删除过的行已从记录集内删掉了。

CRecordset::useBookmarks 如果支持的话,可以在记录集上使用书签。书签会降低数据检索的速度,但会改进数据导航的性能。在只向前滚动记录集上书签无效。

CRecordset::noDirtyFieldCheck 关闭自动的 Dirty 字段检查(双缓冲)。这将改进性能;但您必须通过调用SetFieldDirty SetFieldNull 成员函数,手工将字段标志为 Dirty

CRecordset::executeDirect 不使用已准备好的 SQL 语句。在需改进性能时,如果不调用 Requery 成员函数,就请指定该选项。

CRecordset::useExtendedFetch 执行 SQLExtendedFetch 而不是 SQLFetch。这是用于在只向前滚动记录集上执行大量行提取而设计的。如果在只向前滚动记录集上指定选项 CRecordset::useMultiRowFetch,则会自动开启 CRecordset::useExtendedFetch

CRecordset::userAllocMultiRowBuffers 用户将为数据分配存储缓冲区。如果想自己分配存储量,应将该选项与 CRecordset::useMultiRowFetch 一起使用;否则,框架将自动分配必要的存储量。

如果您愿意的话,可以使用大量行提取改进性能。在打开记录集对象前,可以用 SetRowsetSize 成员函数定义行集的大小。行集的大小指定了一次提取应检索多少条记录。执行大量行提取时,默认行集大小为 25。请注意。如果不执行大量行提取,行集的大小保持固定值 1

在将行集大小初始化后,应调用 Open 成员函数。在此处您必须指定 dwOptions 参数的 CRecordset::useMultiRowFetch 选项,以执行大量行提取。另外,还可以设置 CRecordset::userAllocMultiRowBuffers 选项。大部分记录字段交换机制在提取期间均用数组来存储检索到的多行数据。这些存储缓冲区可由框架自动分配,或者您也可以手工分配它们。指定 CRecordset::userAllocMultiRowBuffers 选项就意味着要由您进行分配。

优化基于 ODBC 的数据库交互

下面的建议适用于任何涉及 ODBC 的交互。这不仅适用于 ODBC 数据库类,而且对那些与基于服务器的数据一起使用的 DAO 数据库类(DAO 使用 ODBC 与数据源进行通信)也适用。这些建议中有很多都是来自于 Colleen Lambert 的文章"ODBCArchitecturePerformanceand Tuning"(位于 Microsoft Developer Network 光盘)。

通过查询驱动程序一致性级别而尽可能多地利用驱动程序的能力。如果不需要将应用程序移植到另一个平台,就可以通过着重关注某个特定驱动程序的能力,使您应用程序的性能达到最佳状态。

避免调用数据源目录例程。这些例程可能会很耗时。试着调用例程一次,并将信息在本地高速缓存。

牢记可伸缩性,并适当地在本地和远程存放数据。设法避免在二进位组合码框中填入来自远程数据源的数据。

SQLExtendedFetch 用于滚动。如果您的驱动程序支持它,这是对 ODBC 数据源进行来回滚动的最快方法。

已准备好的 SQL 语句运行得更快。花费一些时间准备 SQL 调用,以便它们附加到 HSTMT 上。只有该句柄释放后,它们才会被释放。

使用 SQLBindCol 而不是 SQLGetDataSQLBindCol 负责列的存储和数据类型,这样您就不必为结果集而重新获得它。

SQLTypeInfo 在本地高速缓存。某些数据源将该调用作为存储过程进行处理,这执行起来可能会很耗费成本。

尽量少使用连接,并避免反复地断开连接和重新连接。请记住,除 ODBC 驱动程序进行的调用外,它的管理器也进行调用以准备连接。所有这种开销加起来就可能大幅度降低应用程序的速度。

将块提取用于多级驱动程序。多级驱动程序经常将网络性能当作自己工作的一部分使用,并且,依赖于 SQLFetch 而不是 SQLExtendedFetch 会使您的应用程序遭受网络操作奇特行为的影响。

通过全面了解您的 SQL 来优化查询。这可能看似显而易见,但许多程序员实际上只了解有限数量的 SQL 命令。而对 SQL 语句的进一步学习与精通,可能会使得应用程序有快与更快之分。

使用高性能的 DBMS。我们在本白皮书的开头就谈到了这个问题,好的数据源是应用程序的能力与操作的基础。在您的客户端负担得起的前提下,使用最好的数据源。

其它用于优化应用程序的资源

Visual C++ 随带的文档应是关于 MFC 实现 DAO 的第一个信息来源。不仅应该查阅 MFC DAO 示例和 MFC 技术说明,还应查阅 Class Library Reference Programming with MFC

有关 DAO 工作方式的其它信息,请查阅 Microsoft Jet Database Engine Programmer's GuideMicrosoft Press 出版)。

另外还有两篇推荐文章,均位于 Microsoft Developer Network 光盘上,它们是:

"Jet Database Engine ODBC Connectivity",作者:BlackNeil Stephen Hecht

这篇文章详细讲述了 Microsoft Jet 如何使用 ODBC 检索服务器数据。对于所有用 DAO 编写重要服务器应用程序的人,这都不失为一篇必读文章。

"ODBCArchitecturePerformanceand Tuning",作者:LambertColleen

本白皮书提供对 ODBC 工作方式的良好概述,并以现实、有用的方式讲述了性能问题。

 

 

原创粉丝点击