找回密码
 注册
搜索
查看: 4009|回复: 0

[收藏]VC++中调用ADO的常用方法

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。# M$ k9 Y' a4 B6 t6 v
/ f( n3 k" H6 ?
1、 用import导入ADO 的 COM 文件msado15.dll6 ^+ U5 N  y/ H' z* N6 B- e$ V
/ c$ }7 n5 _$ {* u2 D
例如:
2 V: q2 f/ F1 N+ g: k1 D% G
& y/ s) k' K' s  h0 ^  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
, M2 l7 l4 F$ j- ~! B
0 m5 f# {# `( k. p   no_namespace8 Y9 _3 x; }, J+ G! C
$ l) g/ M# `! v1 |9 Z0 F/ X

! Q+ d! @  X% M8 a2、COM 使用时初始化
1 K) L8 L$ r4 G
7 `7 Q( ~! l( U: S8 jHRESULT ComInit()" X0 \% a% v" V$ T* M- p* s0 A
{ / A7 x3 P# A/ |& S) r% X  l
    HRESULT hr = S_OK;             // 默认返回值2 f) d! r/ [  O7 X  ^2 W0 C9 V
    if FAILED(CoInitialize(NULL))  // COM 初始化调用  @. a+ Q- d/ q; f  \+ J! I
    {0 `1 r6 n% i5 x" a6 W/ s6 @
        CoUninitialize();6 C2 x% T) f$ I# @, w* b
        hr = E_UNEXPECTED;6 R( F7 }+ F# |8 ~* h
    }0 P* C/ B( b( ~
    return hr;
) ?5 e8 |9 J+ u}
' p* a  ]3 E# L/ ?# `: ]" l2 c
; r6 Q% V/ d) H& {7 ?" r) S8 S3 q4 C! N9 K1 E. _
3、建立数据库连接8 o% g* a% O8 i# l

; T/ c4 q/ }' A. ?HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名, O6 Y2 _( H( J
                     LPSTR pConnString,                 // 连接字串
: i  ?2 `2 s! M/ _% h, s                     LPSTR pUserPassword ,              // 用户密码
) N& J5 O+ \2 {% \5 F1 ]  {, O- v                     ConnectOptionEnum ConnectOption )  // 连接参数
6 J' M6 O7 J0 J, D, G8 I: u' q9 }% w{
0 p5 |, f+ ]8 f8 u! ^
* F, P+ n4 i% g3 q6 j( H; V    HRESULT hr = S_OK;        // 默认返回值( Q/ q: j, B0 A$ B. c$ a$ G
    _ConnectionPtr ptrConn;   // 定义Connection对象% M+ a' t& V7 m

7 |- O: M" F1 r6 `1 T' u" z    try' Y, R4 h  j3 L6 [' W' ~
    {) j/ R7 o& W& Q1 x2 E# f' D
        // 创建一个连接实体4 y8 T3 O# y' T1 O6 ?! o6 U
        hr = ptrConn.CreateInstance( __uuidof(Connection) );
8 T6 M9 S- I! L/ d* u# g6 ?+ o. g2 z/ b# z- V. ~% y
        // 设定连接等待的最大秒数,默认是15秒
2 M! I, e  l" x+ }        ptrConn->ConnectionTimeout = 20/ K9 W8 S. L  c

( s; F; m4 S" A# l6 v  K        // 打开连接
1 v& e! `& g/ t3 j- s3 M        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );, S2 I- O0 i+ @) S6 o1 Y
        return hr;
5 a% G: s$ G0 w3 m    }
% l, w( K) b$ D8 P    catch( _com_error & pComError )6 l& Q" {5 A7 ~2 Q1 f  I
    {
2 d# Q4 u3 P4 d2 `& {        …… // 错误处理7 k: Q' @" F) c( G
        return E_UNEXPECTED;. f, Z5 v4 G7 E, P/ x0 x
    }# v& u: r  n1 K
}, D7 b9 x/ s9 w- r" p# m0 M: l

; N* p& i! U5 ]& N0 @  m4 q3 [; Y0 b: V* p  D1 X' a
4.执行一个SQL 查询,得到数据集(recordset)
( p5 S: Q( W/ S- u* e9 f1 f' A! S7 O% H/ A% _8 f
_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
3 i) B9 O+ T* P{
9 i: T3 |" Z! R; m* z) u4 n2 b  Y: w    try
7 s7 H7 r3 I+ H# M9 h" ^: d' w    {; e) S/ v( e+ a; g6 g  V
        RecordsetPtr ptrRS; // recordset 对象4 G: m- T" D) g/ A7 U
$ E* t* _' W! p/ w0 D
        // 创建recordset 对象实体
' e4 y( ?+ P' v+ c/ H, [        ptrRS.CreateInstance( __uuidof(Recordset) );8 e$ Y6 b+ r- R$ `" N1 Y
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, " P7 @9 H5 T; B6 D: e4 y5 K
adLockUnspecified, adCmdText );: u: Y, I* \- C, [3 @. S
% _5 h" j1 N* _. c. E
        或者8 ]  q# r/ S2 B% q: _3 F
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
) ^5 a& @' x6 C/ ]- D        return ptrRS;+ N5 X5 ^) {5 W5 t$ q
    }: a- u+ u% X9 a0 e3 ~7 M* b/ D# a3 N
    catch( _com_error & a_pComError )
2 U% b; ~# C- O    {
4 G; C( m1 l" a# Q9 ?! ^        ….// 错误处理
4 d# R  N" I! r        return NULL;
/ o9 J+ Z8 ^( Z, }2 D1 Z* s" k    }; ^; D  W' i; `+ B
}
& y+ t0 c- B6 z1 C+ R) S  z- O7 M3 J& e: {  J/ {  s

  F) {! b% X, }' l7 D% s5.通过数据集(recordset)得到列的名称2 x! I# g# K6 F
+ A% \. D; F0 V9 T! Z
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
' K; O: x6 q, @                        char strColNames[][255],
& i6 l( t/ n& V" o0 l+ ]; l; f                        DataTypeEnum iColTypes[] )
- l8 U6 H7 w& y0 n8 V- a{. \4 k- D2 n4 p) E8 A6 X4 r' P! [1 l+ [
    try/ {0 L$ [% `$ a- T& G- [
    { // 参数变量& e! h) b# y$ T7 A9 A( e; }4 S9 s
        _variant_t l_vaIndex;8 S1 R# h, s7 b0 {" T$ ^5 Z& L

8 r9 O/ b1 g& W- ?) f7 Z6 i- l        l_vaIndex.vt = VT_I2;; L2 y$ a. i' c  g7 {

- M: k  K) e+ A        // COLUMNS总数6 l. B9 I$ }  o) _
        long lColCount;
+ F! k- v9 F1 x- U$ q0 p  ^2 R" X4 a7 ~4 ^- t( v
        lColCount = ptrRs ->Fields->Count;) W9 O4 a8 ~$ y' K
+ G- W8 \( m" V' x8 A* A) {
        // 循环取得列的属性和名称% l+ U3 i. s; l; Q
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
& _* K  ^8 ]" @7 z0 W        {
# T+ S% r! X% b( a( z            l_vaIndex.iVal = iIndex; // 设置循环索引
( D7 }" K* W# }7 Z6 d/ d8 x; U: R; j" |7 R
            // 取得字段名称
0 e! l1 F5 n5 U2 ]  `/ g            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);' U) ~# f7 `  Q2 j. G! W

% S! E- r4 M8 r: d1 N" g+ i: f            // 取得字段属性
% C5 X; C1 a7 E/ _9 O/ u1 K            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;9 i$ ?! V; A  }! T
        }$ \. d% Y& l7 e+ I$ Q4 }8 ^
        return S_OK;. A. [) Z1 ^& L( w8 g0 p2 b% C
    }" j- I' C2 l, s- C( o5 ]% q8 s
    catch( _com_error & a_pComError ), U9 ^0 j' a, k" R
    {( Z8 b9 R# X0 _7 P
        …. // 错误处理
) K' P. L1 f6 p$ I9 d        return E_UNEXPECTED;+ W8 Y1 t. u' E8 K. I
    }
+ Y) D& O  n2 X/ _, s, f    catch(...)! u2 L# W( w1 W2 K5 {7 S
    {; E+ \& Y  K3 [$ n& x
        …. // 错误处理" x7 s$ p2 d) G. F1 }
        return E_UNEXPECTED;
; a8 t/ D# E4 T; P: j; k1 E0 m    }
% k9 E' ~1 C! o! e- n/ K}; F8 S# w! E  v. C" {
/ P- w* A& o1 s! R0 L  S2 v
6 I" d, \- ]& N& [
6.通过数据集(recordset)得到当前行记录
7 \# M- E( r# x
( i5 l6 V+ `& ]: w- P  uHRESULT getOneRecord( _RecordsetPtr ptrRs,2 s$ l0 M9 `$ ?8 ]  k; Z
                      const long lNoOfColumns,9 r- @# [4 z: A$ T
                      _variant_t varValue[] )
) m/ l* Y, u, A{2 q# y  Z- n; \8 W* t! V/ r1 m6 m
    try
9 s; F7 J8 I8 M5 e    {
( w" g  k/ J7 ~& r7 E        // 参数变量- t3 ^# Y" g5 a0 w' X7 F+ Y1 I$ x
        _variant_t l_vaIndex;
  d7 G" \7 c- a3 X, n3 i$ h        l_vaIndex.vt = VT_I2;1 \1 m8 W1 q9 l7 f0 r- H

) w2 v) Z8 A( `' A; u' g: p        // 循环取得列的值) ]- Q& Q4 w# l2 P
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )
. ?' E, x) v- R        {
' `* J  e( ]9 u            l_vaIndex.iVal = lIndex;
2 ]- D; @5 K- B4 m4 c+ E7 p
" |. V+ O! h& J/ R  q9 o: Q4 I' k            // 取得字段值
% \; r. Z* h1 u$ P  r! @1 \" z            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;( i; F% E5 f! y5 D2 W
        }
% h+ \( w! U- X& U7 {, \        return S_OK;7 ]! y& T1 s' N8 X6 V( g
    }$ g0 ?/ Y6 l% R+ g
    catch( _com_error & a_pComError )
  S! W& V) f1 L/ {" \2 ^: `    {
0 S+ Q' b( A( j3 q        …. // 错误处理9 m  A8 T/ G( o/ j( T# N
        return E_UNEXPECTED;- g0 O0 x7 H: l; \  u( C3 T
    }9 G  r& W6 r' E5 X) g8 s/ [( y
    catch(...)% T4 }  W7 e" [
    {
: [: x7 b* Z8 y( d- v        …. // 错误处理
  n5 o" n" E' w7 o0 @) M        return E_UNEXPECTED;
- l% L* R' P  h1 I    }
9 v: C2 G* x0 ~# ^* r8 S) h}( o% N+ ?% |4 M' ~+ I

8 V4 ~- A2 g6 S- b  r7 F  e
4 `  U9 F6 U" p' T& I& O7.出错情况下错误信息的取得
- o) X3 c8 ?# g4 x5 q+ ~/ C4 d) y( r1 K5 c5 N& c
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
* V2 C; i" N* R; N% ^' U$ r  T( C{
/ f/ |) a) |* ~6 t  e) O* v; N    // COM 错误取得! `7 O7 ~4 g# e
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常+ g* J' M* d0 _& D. s
    char lpComErrorStr512];
) z! i# s+ R8 T
# c7 J& R; S: _+ o! H# |    sprintf( lpComErrorStr512,
) `' c, f( \, n* O( X4 s; z             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",: y* B6 S/ _3 M( _
             pComError.Error(),                  // 错误编号. v0 h; V2 `; U' ]
             pComError.ErrorMessage(),           // 错误信息
& B+ W' y. y! G( U             (LPCSTR) pComError.Source(),        // 错误源
  {5 R, `5 e- g2 s6 j9 F' c: @# u5 e             (LPCSTR) pComError.Description() ); // 错误描述9 z8 a$ {: p+ U

  p' r& z$ l' C! ~. }) R+ U    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息' E0 c, A4 p; @! O
    // ADO错误取得
& B$ ?. u$ h! O" k) _; v8 o5 d' `& q2 K# C% I" Z1 {: D! s
    ErrorPtr pErr = NULL;
8 Y( E" l' {+ O2 L9 c/ N    if( (ptrConn ->Errors->Count) > 0)
6 O3 s* `. ^1 d: r* t) k( g9 C9 l    {
: Z% ]8 J. W) L3 w3 [; ], I" B        long nCount = ptrConn ->Errors->Count;
: Q. r5 ?0 |% H& ]: s. W        for( long i = 0; i < nCount; i++ )
; e) Y# n$ b) @; Y7 V        {6 {. V+ ^" f) j& K. R
            pErr = a_pConnPtr->Errors->GetItem(i);0 Z! n+ |1 w! k" s6 w' }' u# C
: [8 R5 h, {* d' V1 g- P
            char l_pchErrorString[512];' c- v6 |7 f9 l0 S
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
+ h# E( l" K$ O: U6 @                     pErr->Number,         // 错误编号
' M; t* ^" l& N7 h( s# l& y                     pErr->Description );  // 错误描述( U2 |  E) c; D; {% m' ]
        }
9 u7 \5 F6 E' I    }
! D" O) v" U  u# h% i+ }' Q. A) H! J* _2 R/ X4 `+ a
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
# H0 T6 |$ E6 k2 G    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2025-5-5 04:26 , Processed in 0.014593 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表