65.9K
CodeProject 正在变化。 阅读更多。
Home

ADO:101 级教程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.47/5 (19投票s)

2004 年 5 月 3 日

CPOL

3分钟阅读

viewsIcon

109404

downloadIcon

2573

ActiveX 数据对象 (ADO) 的 101 级教程。

引言

ActiveX 数据对象,更常被称为 ADO,是微软世界中一种流行的数据库访问技术。 微软已经开发并推广这个编程接口很多年了,并且在 .NET 的情况下,为了适应 .NET 世界,重新设计了大部分(以及一个新的品牌 -- ADO.NET)。

尽管 ADO.NET 已经出现,但仍然存在大量用 C++ 编写的遗留 ADO 代码。 因此,那些不是从小就接触 ADO 的程序员,在未来的许多年里,仍将面临维护 C++ 中的遗留 ADO 代码的问题。

在这篇简短的文章中,我将提供 C++ 中 ADO 的一个简单介绍。这个 101 级别的教程将重点介绍以下常用的 ADO 操作:

  • 初始化 COM 子系统
  • 建立数据库连接
  • 发出一个简单的 select 语句
  • 检索记录结果
  • 关闭结果和连接对象

本文的目标读者是熟悉 C++ 并且对 ActiveX 模板库 (或 ATL) 有一定了解,但很少或没有进行过 ADO 编程的人。 我在这里包含的代码可以快速地剪切和粘贴到新的 C++ 源文件中,并且我鼓励任何需要重新使用此代码的人抓取它并运行。

从 C++ 中使用 ADO 的一个潜在问题是管理 COM 对象。 如果您正确使用智能指针,那么对象将在超出范围时自动释放。 我提供的示例将演示其中的一些内容,但如果您需要更多详细信息,最好阅读像 XYZ 这样的书。

让我们开始吧!! 首先,我们必须选择要使用的 ADO 版本。

1. 导入类型库

可以导入多个 ADO 类型库,并且它们因版本而异。 可用的类型库列表将根据您安装的 Windows 操作系统和开发工具(Visual C++ 6、Visual C++ 7.x 等)而有所不同。 在我的系统中,C:\Program Files\Common Files\System\ado 子目录中,列表包括以下内容:

  • msado20.tlb
  • msado21.tlb
  • msado25.tlb
  • msado26.tlb

对于此示例,我选择了最新的类型库文件,版本 msado26.tlb。 然后,我添加了以下 import 语句

#import "c:\program files\common files\system\ado\msado26.tlb" no_namespace rename( "EOF", "A_EOF" )

2. 初始化 COM 并创建连接对象

我的示例中的第一步包括初始化 COM 并创建 ADO 连接对象的实例。

      HRESULT hr = ::CoInitialize(NULL);
      if (FAILED(hr))
      {
            return false;
      }
      _ConnectionPtr pConnection;
      hr = pConnection.CreateInstance(__uuidof(Connection));
      if (FAILED(hr))
      {
            return false;
      }

3. 建立数据库连接

现在,我们准备打开一个数据库连接。 此操作放在 C++ 的 try/catch 块中。 如果此操作失败,则会抛出一个 _com_error 类型的异常并立即捕获

      try
      {
            pConnection->Open(strConnectionString, 
               _T(""), _T(""), adOpenUnspecified);
            // ...
      }
      catch (_com_error&)
      {
            ::CoUninitialize();
            // ...
      }

4. 构造 SQL 语句

最后,我们准备执行 SQL 语句。 我将使用最简单的示例来发出 "SELECT GETDATE()",它返回一个单行/单列的结果。

_CommandPtr pCommand(__uuidof(Command));
pCommand->ActiveConnection = pConnection;
pCommand->CommandText = "SELECT GETDATE()";

5. 执行语句并检索结果

与 JDBC 等其他数据库抽象层不同,ADO 语句在结果集对象上执行。 要执行语句,您可以创建一个 command 对象并将其设置为或直接链接到也创建的 recordset 对象。 另一种选择是完全绕过创建 command 对象的过程,并立即执行 recordset,在 recordset 对象上指定 SQL 语句文本。

  _RecordsetPtr pRecordSet(__uuidof(Recordset));
   pRecordSet->PutRefSource(pCommand);   
   _variant_t vNull(DISP_E_PARAMNOTFOUND, VT_ERROR); 
    pRecordSet->Open(vNull, vNull, adOpenDynamic, 
       adLockOptimistic, adCmdText);
   
   char szTimeStamp[64] = { 0 };
   if (!pRecordSet->A_EOF)
   {
         _Recordset **ptrResults = NULL;
         pRecordSet->QueryInterface(__uuidof(_Recordset),
            (void **) ptrResults); 

上面的代码检索了生成的 recordset。 但是,首先,它会在读取返回的行和列之前检查 EOF 状态。

6. 迭代结果

返回的 recordset 对象非常简单;它只包含单行单列数据。

      // SELECT GETDATE() returns one row without a column name
      _variant_t vField(_T(""));
      _variant_t vResult;
      vResult = pRecordSet->GetFields()->GetItem(vField)->Value;
      _bstr_t strTimeStamp(vResult);
      strncpy(szTimeStamp, (char*) strTimeStamp, 63);
      if (szTimeStamp > 0)
      {
            char szFeedback[256] = { 0 };
            sprintf(szFeedback, "SQL timestamp is: %s", szTimeStamp);
            AfxMessageBox(szFeedback, MB_OK | MB_ICONINFORMATION, 0);
      }

7. 释放资源

pRecordSet->Close();
pConnection->Close();
::CoUninitialize();

在这里,我们通过关闭 recordset 和连接以及释放为 COM 分配的资源来完成。

ADO:101 级别教程 - CodeProject - 代码之家
© . All rights reserved.