中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > Windows编程
VC++程序员应当如何阅读ADO文档(2)
作者:佚名 时间:2007-12-10 17:11 出处:csdn 责编:月夜寒箫
              摘要:VC++程序员应当如何阅读ADO文档(2)
VC++与VB中编码时的约定

 

 

 

下面是ADO文档中关于如何使用VB和VC++编写代码的一个概览。

 

声明一个ADO对象

 

 

VB中,一个ADO对象变量(此处以Recordset对象为例)如下声明:

 

 

Dim rst As ADODB.Recordset

 

 

子句"ADODB.Recordset"是在注册表中登记的Recordset对象的ProgID。而一个Record对象的实例如下声明: Dim rst As New ADODB.Recordset

 

 

或者:

 

 

Dim rst As ADODB.Recordset

 

 

Set rst = New ADODB.Recordset

 

 

而在VC++中,#import为所有的ADO对象生成了智能的指针类型。比如一个指向_Recordset对象的指针变量的数据类型为_RecordsetPtr,并如下声明:

 

 

_RecordsetPtr  rs;

 

 

而一个_Recordset对象的实例则如下声明:

 

 

_RecordsetPtr  rs("ADODB.Recordset");

 

 

或者:

 

 

_RecordsetPtr  rs;

 

 

rs.CreateInstance("ADODB.Recordset");

 

 

或者:

 

 

_RecordsetPtr  rs;

 

 

rs.CreateInstance(__uuidof(_Recordset));

 

 

CreateInstance方法被成功调用后,该变量可被如此使用:rs->Open(...);

 

 

注意,如果变量是一个类的实例则用"."操作符,若是一个指向实例的指针则应使用"->"操作符。

 

 

一个变量能通过两种方式被使用。因为"->"操作符被重载,允许一个对象实例类似一个接口指针那样被使用;"->"操作符返回该指针;而由这个返回的指针访问_Recordset对象的成员。

 

 

编写省略String参数的代码

 

 

当你需要利用VB编写省略String参数的代码时,只需简单的略掉该操作数即可。但在VC++中,你必须指定该操作数为一个包含空字符串的_bstr_t变量:_bstr_t strMissing(L"");

 

 

编写省略Variant参数的代码

 

 

当你需要利用VB编写省略Variant参数的代码时,只需简单的略掉该操作数即可。但在VC++中,你必须指定所有的操作数。编写省略Variant参数的代码只需将该Variant设为专门的值,可以定义一个值为DISP_E_PARAMNOTFOUND、类型为VT_ERROR的_variant_t。还可以使用#import编译指示符提供的与之等价的常量vtMissing。

 

 

_variant_t  vtMissingYours(DISP_E_PARAMNOTFOUND, VT_ERROR);

 

 

或者:

 

 

...vtMissing...;

 

 

声明一个Variant

 

 

VB中,一个Variant如下被声明:

 

 

Dim VariableName As Variant

 

 

VC++中,定义一个_variant_t型的变量即可。主要有以下几种形式。注意:这些声明只是你在变成时刻采用的一个粗略的思路。

 

 

_variant_t  VariableName(value);

 

 

_variant_t  VariableName((data type cast) value);

 

 

_variant_t  VariableName(value, VT_DATATYPE);

 

 

_variant_t  VariableName(interface * value, bool fAddRef = true);

 

 

使用Variants数组

 

 

VB中,利用Dim语句可以进行Variant数组的编程,并可以使用Array的函数。见如下示例:

 

 

Public Sub ArrayOfVariants

 

 

Dim cn As ADODB.Connection

 

 

Dim rs As ADODB.Recordset

 

 

Dim fld As ADODB.Field

 

 

cn.Open "DSN=pubs", "sa", ""

 

 

rs = cn.OpenSchema(adSchemaColumns, _

 

 

                     Array(Empty, Empty, "authors", Empty))

 

 

For Each fld in rs.Fields

 

 

   Debug.Print "Name = "; fld.Name

 

 

Next fld

 

 

rs.Close

 

 

cn.Close

 

 

End Sub

 

 

以下的代码演示了如何通过一个_variant_t使用一个SafeArray数组。注意注释对应了编码的步骤。

 

 

1.再一次的,TESTHR()内置函数被定义以利用预存的错误处理机制。

 

 

2.如果你只需要一个一维数组,你可以使用SafeArrayCreateVector,而非SAFEARRAYBOUND声明与SafeArrayCreate函数。下面的代码使用了SafeArrayCreate:

 

 

   SAFEARRAYBOUND   sabound[1];

 

 

   sabound[0].lLbound = 0;

 

 

   sabound[0].cElements = 4;

 

 

   pSa = SafeArrayCreate(VT_VARIANT, 1, sabound);

 

 

3.枚举常量adSchemaColumns定义的模式,决定了与TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME和COLUMN_NAME四列相联系。为此,一个有四个Variant元素的数组被创建。而对应于第三列TABLE_NAME的值被设置。

 

 

由若干列组成的返回的Recordset只是对应的所有列的一个子集,并且每一行的值保持了一一对应。

 

 

4.熟悉SafeArrays的人也许会对退出前没有调用SafeArrayDestroy()感到惊奇。实际上,在这种情况下调用SafeArrayDestroy()会导致一个运行时的异常发生。这是因为vtCriteria的析构函数会在_variant_t超出使用范围时调用VariantClear(),从而释放SafeArray。只调用SafeArrayDestroy,而没有手动清除_variant_t,将会导致析构函数试图去清除一个无效的SafeArray指针。如果要调用SafeArrayDestroy(),那么代码应该象这样:

 

 

   TESTHR(SafeArrayDestroy(pSa));

 

 

   vtCriteria.vt = VT_EMPTY;

 

 

   vtCriteria.parray = NULL;

 

 

实际更像是让_variant_t管理SafeArray。

 

完整的代码如下:

 

 

#import "c:\Program Files\Common Files\System\ADO\msado15.dll"

 

 

   no_namespace rename("EOF", "EndOfFile")

 

 

#include <stdio.h>

 

 

// Note 1

 

 

inline void TESTHR( HRESULT _hr )

 

 

   { if FAILED(_hr) _com_issue_error(_hr); }

 

 

void main(void)

 

 

CoInitialize(NULL);

 

 

   try   {

 

 

   _RecordsetPtr   pRs("ADODB.Recordset");

 

 

   _ConnectionPtr  pCn("ADODB.Connection");

 

 

   _variant_t      vtTableName("authors"),

 

 

                   vtCriteria;

 

 

   long            ix[1];

 

 

   SAFEARRAY       *pSa = NULL;

 

 

   pCn->Open("DSN=pubs;User ID=sa;pwd=;Provider=MSDASQL;", "", "",

 

 

               adConnectUnspecified);

 

 

// Note 2, Note 3

 

 

   pSa = SafeArrayCreateVector(VT_VARIANT, 1, 4);

 

 

   if (!pSa) _com_issue_error(E_OUTOFMEMORY);

 

 

// 为第三个元素赋值TABLE_NAME(索引值2).

 

 

   ix[0] = 2;     

 

 

   TESTHR(SafeArrayPutElement(pSa, ix, &vtTableName));

 

 

// 由于Variant没有SafeArray的构造函数,所以手工设置Variant的数据类型和值。

 

 

   vtCriteria.vt = VT_ARRAY | VT_VARIANT;

 

 

   vtCriteria.parray = pSa;

 

 

   pRs = pCn->OpenSchema(adSchemaColumns, vtCriteria, vtMissing);

 

 

   long limit = pRs->GetFields()->Count;

 

 

   for (long x = 0; x < limit; x++)

 

 

      printf("%d: %s\n", x+1,

 

 

         ((char*) pRs->GetFields()->Item[x]->Name));

 

 

// Note 4

 

 

   pRs->Close();

 

 

   pCn->Close();

 

 

   }

 

 

   catch (_com_error &e)

 

 

   {

 

 

   printf("Error:\n");

 

 

   printf("Code = %08lx\n", e.Error());

 

 

   printf("Code meaning = %s\n", (char*) e.ErrorMessage());

 

 

   printf("Source = %s\n", (char*) e.Source());

 

 

   printf("Description = %s\n", (char*) e.Description());

 

 

   }

 

 

   CoUninitialize();

 

 

}

 

 

使用属性的Get/Put/PutRef

 

 

VB中,属性的名称并未被检验,无论它是被读取、被赋值,或者赋予一个引用。

 

 

Public Sub GetPutPutRef

 

 

Dim rs As New ADODB.Recordset

 

 

Dim cn As New ADODB.Connection

 

 

Dim sz as Integer

 

 

cn.Open "Provider=sqloledb;Data Source=yourserver;" & _

 

 

         "Initial Catalog=pubs;User Id=sa;Password=;"

 

 

rs.PageSize = 10

 

 

sz = rs.PageSize

 

 

rs.ActiveConnection = cn

 

 

rs.Open "authors",,adOpenStatic

 

 

' ...

 

 

rs.Close

 

 

cn.Close

 

 

End Sub

 

 

以下是VC++关于Get/Put/PutRefProperty的演示

 

 

1.这个例子演示了省略字符串参数的两种形式:一种是采用常量strMissing,另一种则是由编译器自动生成一个临时的存在于Open方法使用期间的_bstr_t。

 

 

2.因为操作数已经是(IDispatch *)的指针,所以没有必要将rs->PutRefActiveConnection(cn)的操作数再进行类型转换。

 

 

#import "c:\Program Files\Common Files\System\ADO\msado15.dll"

 

 

   no_namespace rename("EOF", "EndOfFile")

 

 

#include <stdio.h>

 

 

void main(void)

 

 

CoInitialize(NULL);

 

 

   try

 

 

   _ConnectionPtr  cn("ADODB.Connection");

 

 

      _RecordsetPtr   rs("ADODB.Recordset");

 

 

      _bstr_t         strMissing(L"");

 

 

      long            oldPgSz = 0,

 

 

                      newPgSz = 5;

 

 

// Note 1

 

 

      cn->Open("Provider=sqloledb;Data Source=a-tima10;"

 

 

         "Initial Catalog=pubs;User Id=sa;Password=;",

 

 

         strMissing, "",

 

 

         adConnectUnspecified);

 

 

         oldPgSz = rs->GetPageSize();

 

 

   // -or-

 

 

      oldPgSz = rs->PageSize;

 

 

      rs->PutPageSize(newPgSz);

 

 

   // -or-

 

 

      rs->PageSize = newPgSz;

 

 

// Note 2

 

 

      rs->PutRefActiveConnection( cn );

 

 

      rs->Open("authors", vtMissing, adOpenStatic, adLockReadOnly,

 

 

               adCmdTable);

 

 

      printf("Original pagesize = %d, new pagesize = %d\n", oldPgSz,

 

 

               rs->GetPageSize());

 

 

      rs->Close();

 

 

      cn->Close();

 

 

   }

 

 

   catch (_com_error &e)

 

 

   {

 

 

      printf("Description = %s\n", (char*) e.Description());

 

 

   }

 

 

   ::CoUninitialize();

 

 

}

 

 

使用GetItem(x)和Item[x]

 

 

下面是VB中关于Item()的标准与交互语法的演示。

 

 

Public Sub GetItemItem

 

 

Dim rs As New ADODB.Recordset

 

 

Dim name as String

 

 

rs = rs.Open "authors", "DSN=pubs;", adOpenDynamic, _

 

 

         adLockBatchOptimistic, adTable

 

 

name = rs(0)

 

 

' -or-

 

 

name = rs.Fields.Item(0)

 

 

rs(0) = "Test"

 

 

rs.UpdateBatch

 

 

' Restore name

 

 

rs(0) = name

 

 

rs.UpdateBatch

 

 

rs.Close

 

 

End Sub

 

 

以下则是VC++关于Item的演示

 

 

当访问collection中的Item时,索引值2必须被转换为long类型以确保正确的构造函数被调用。

 

 

#import "c:\Program Files\Common Files\System\ADO\msado15.dll"

 

 

   no_namespace rename("EOF", "EndOfFile")

 

 

#include <stdio.h>

 

 

void main(void)

 

 

{

 

 

   CoInitialize(NULL);

 

 

   try {

 

 

      _RecordsetPtr   rs("ADODB.Recordset");

 

 

      _variant_t      vtFirstName;

 

 

      rs->Open("authors",

 

 

               "Provider=sqloledb;Data Source=a-tima10;"

 

 

               "Initial Catalog=pubs;User Id=sa;Password=;",

 

 

               adOpenStatic, adLockOptimistic, adCmdTable);

 

 

      rs->MoveFirst();

 

 

// Note 1.取得一个字段的名称

 

 

      vtFirstName = rs->Fields->GetItem((long)2)->GetValue();

 

 

   // -or-

 

 

      vtFirstName = rs->Fields->Item[(long)2]->Value;

 

 

      printf( "First name = '%s'\n", (char*) ((_bstr_t) vtFirstName));

 

 

      rs->Fields->GetItem((long)2)->Value = L"TEST";

 

 

      rs->Update(vtMissing, vtMissing);

 

 

   // 恢复原名称

 

 

      rs->Fields->GetItem((long)2)->PutValue(vtFirstName);

 

 

      // -or-

 

 

      rs->Fields->GetItem((long)2)->Value = vtFirstName;

 

 

      rs->Update(vtMissing, vtMissing);

 

 

      rs->Close();

 

 

   }

 

 

   catch (_com_error &e)

 

 

   {

 

 

      printf("Description = '%s'\n", (char*) e.Description());

 

 

   }

 

 

   ::CoUninitialize();

 

 

}

 

 

 

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有