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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
( G# h. n5 F/ Y  v8 O2 b' X$ V9 g/ K& b2 T1 |
1、 用import导入ADO 的 COM 文件msado15.dll
' v" K, C( f& T9 j4 n9 [
3 H6 A: ?# o  ^例如:8 ^1 z2 y. R$ U$ K
* O* p) x& j/ I8 J& _! \2 D
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
8 m6 e4 z: ^% V
2 f( A8 N# ~1 {. X   no_namespace, S) S9 X. L7 e4 e
0 }/ D1 ?4 B& d4 h; [# ~+ H0 ~

! K+ [# L' A5 ~9 w3 v5 s2、COM 使用时初始化
" V0 k5 \7 O# d: w8 k4 h) {3 m2 m6 l, @$ }, p! n1 }& W
HRESULT ComInit()& u8 w+ S# ?3 c. Z& |2 H
{ " e' d2 S, u) y: `2 X4 u; T; L
    HRESULT hr = S_OK;             // 默认返回值* G/ ^7 Y# z% p& B: g6 w6 d
    if FAILED(CoInitialize(NULL))  // COM 初始化调用8 ^, g& p3 S  ~# [; ?' {/ U/ C
    {9 G2 u6 k/ A3 ~! {
        CoUninitialize();
( N- _' z5 [( j- O2 U* o2 F        hr = E_UNEXPECTED;5 ?8 y4 T0 [) g5 R- X  j
    }
# T- X7 X3 z3 E    return hr;
- g6 n9 W8 I% N" V$ x}# Z# A- ^# Q) X% _; K1 Z: r4 H

+ H, \- }7 Z& M7 b5 j
, z; m9 u; D5 X8 p* E" [3、建立数据库连接
( M$ K$ ~( e4 ~, R8 P5 k9 u( @8 J- D2 s- ?8 F# n. `
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名! T& Q9 W; f! Z2 ^5 W
                     LPSTR pConnString,                 // 连接字串
! C& [% o5 R* o/ K9 a! p# F1 C                     LPSTR pUserPassword ,              // 用户密码
5 c1 p2 q( B, H& I5 `' k$ M' B8 ~                     ConnectOptionEnum ConnectOption )  // 连接参数
4 S& E: m( f! r7 B8 h' S{6 {, G5 l$ L6 v5 [* Z3 U9 M$ ^
1 b# s0 G# O& v+ ^' L$ i, ^; N
    HRESULT hr = S_OK;        // 默认返回值% Y# d$ t! G/ m" T* k
    _ConnectionPtr ptrConn;   // 定义Connection对象$ E) a5 A% a& F

( P$ b2 u* r4 P. [; r    try
0 J8 N& [1 N  S/ r1 D1 I2 c3 {    {. L4 V: r# w; |; [# W
        // 创建一个连接实体
0 H* a$ c$ G. o, q7 N) i        hr = ptrConn.CreateInstance( __uuidof(Connection) );
# g; @/ E: N9 [5 t& T
0 S# B1 M0 z% `( a        // 设定连接等待的最大秒数,默认是15秒
) s* U5 L+ _4 c+ B        ptrConn->ConnectionTimeout = 20& r9 a1 ]: _! n8 \: F, W  {7 c, G

6 k7 G8 y+ [6 s* @        // 打开连接" p3 q) E! n5 n5 M1 q- E8 F2 G3 l
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
7 I" F' z: C( p3 W+ q( q        return hr;
) g( {  Q+ j4 p( b; n, j. R    }
4 U( N4 Q& S5 ~    catch( _com_error & pComError )+ y6 a( T1 s2 t# I$ @5 A
    {) ^/ W# u& o  ^  n/ j" Q
        …… // 错误处理% f9 x& ^* c1 f& y( U6 V
        return E_UNEXPECTED;
$ L9 ^& K$ P$ [. ^4 @) K    }
7 w3 _5 Y: S9 G  y1 H}* W+ x' _- T! p9 E7 E

% b5 |) w$ x5 H- s: N7 T! F' C+ t5 c/ M
4.执行一个SQL 查询,得到数据集(recordset)
  k: H7 y# B! v  q
. v+ z$ Q+ V4 e0 M4 m0 v2 ~- z_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn ); J/ h- Y( N: d+ c! w
{
, y: s; O: r/ @7 n5 o# |    try
5 R" w; W* B5 n2 q5 d    {- ]% U* b: ?" G. U0 ^+ x4 `8 P" t, G- g
        RecordsetPtr ptrRS; // recordset 对象
; S+ A  I$ A4 c! J- q3 ^4 n; }+ B$ f2 {) y3 o5 m& B+ {
        // 创建recordset 对象实体
' `; w* v$ o, }7 H( x        ptrRS.CreateInstance( __uuidof(Recordset) );
" R8 k& g5 I) F  t  ~. m( a8 |        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, ! D' E; h' r4 ?& q/ W. r- P
adLockUnspecified, adCmdText );- p) R3 r9 B2 _8 v1 i. y. P

# U6 E0 `3 D& H+ x/ T        或者3 [* F. v5 m! U0 m* `* c
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );5 m5 x5 A: n+ P6 I, N+ A: V1 x
        return ptrRS;
. `& o3 y% O' v" X( |/ }6 ?! F    }
) h- E- A4 ~% d! O+ D- {* b/ L" G& X    catch( _com_error & a_pComError )  K( ^7 M7 b1 o3 [" F8 F
    {4 X) G: N: u$ I# q0 V3 G; O1 e
        ….// 错误处理# z1 c0 W. T& V4 C" f" h  U
        return NULL;6 j& g7 {  r, h" P9 l& g
    }
5 D  H" f9 i' b$ C$ n9 Q, z( k  q}
4 b6 {, o5 b, o8 ?' |1 l* M# C6 u( a8 N' s2 a' m

' H5 Z6 d$ U$ K- c5.通过数据集(recordset)得到列的名称
* L! l. L; j" G* I" K5 e8 V
9 J7 J# F3 ~$ A$ P0 h1 IHRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
  T- S/ L% ]3 F; K. H                        char strColNames[][255],8 w- M# z7 j3 Q+ A& @3 c
                        DataTypeEnum iColTypes[] )
2 X/ A8 \$ o( U8 T9 p: l{% K. f4 N3 ~2 V4 O% E  H% |( R9 z4 g
    try8 Z$ \# \: X' A; f
    { // 参数变量8 g6 g; \( ~8 {4 S
        _variant_t l_vaIndex;  d" D7 Z6 d9 L4 }$ f4 E9 u0 ]
1 }( W% B1 m& z$ J/ {
        l_vaIndex.vt = VT_I2;1 z, b# r" e7 |2 r# I  W9 d& K

  }% |1 ?5 j" B! x        // COLUMNS总数
: I4 A9 f( t9 b4 Y. t9 k$ i: z; k        long lColCount;& f/ \" R; e' v+ h) E0 e& P
* p$ S6 B& p( _" h# s
        lColCount = ptrRs ->Fields->Count;
* }6 N! ]9 r! j2 q# x% W
0 t5 `6 E1 V( m0 W6 C: `2 j. F( r        // 循环取得列的属性和名称
9 w  Y4 _. P6 a2 T4 S/ J        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )3 `! Y+ ~' g1 J7 p! n
        {/ z+ p% A( ]0 ~! b0 L- [
            l_vaIndex.iVal = iIndex; // 设置循环索引
* ~" W$ U( k3 q0 c' j9 k
4 h! i0 F$ ?5 D/ g/ ~) L            // 取得字段名称6 I" z9 I3 c& x+ @! M6 j9 q
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);3 [6 ?8 G# i4 u2 N
8 a. ?4 g- j. }; x8 z- P4 |
            // 取得字段属性/ x( W0 ~3 L- s3 i7 j! H
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;
% Q1 J; {: Q- v        }
+ f5 F5 d0 j9 p3 m$ b. @& W  D        return S_OK;
& {" U3 f- z- o( ]    }
' Q8 R3 D1 j7 H; g    catch( _com_error & a_pComError )3 T5 L; f- [* O3 l7 {- `1 O+ L8 M
    {& L. d' d( _- L( G8 y, A# n- N" q  O
        …. // 错误处理" q) j, V6 f0 n0 n
        return E_UNEXPECTED;. `" Q  ^  ]9 E! v4 P2 U
    }
4 u7 \& s( n, d. R    catch(...)
- ], a, r2 A4 A5 U4 A7 H9 q' X4 p    {
2 P  F3 B# ?8 m% }- u, Q" a        …. // 错误处理& b" f" e$ |$ p
        return E_UNEXPECTED;
; I" ]8 t2 H1 B, C. @2 y! ]8 ?    }7 H. ~) d7 p) ]# O- e
}
1 L6 P: A# i8 C! P3 C2 G- a8 B  ?1 }4 |; {4 V
7 `2 u  o( d  ?0 b$ |4 L/ v4 x* J
6.通过数据集(recordset)得到当前行记录) E6 ^3 s: m/ c5 a, F3 s& t

9 I9 e5 i5 b7 f' r. a7 D1 oHRESULT getOneRecord( _RecordsetPtr ptrRs,
% w7 r6 l( n- k                      const long lNoOfColumns,0 }! T! g( }" I+ ~3 L
                      _variant_t varValue[] ), @1 k' V, f* G" `1 O8 N) ~
{! ]. }; Y6 U3 `5 }' [) X
    try
$ H8 J; E* E+ Z. l    {
# m/ _" u: }2 w5 Z" n8 n% q        // 参数变量
# L* c# w" e/ u        _variant_t l_vaIndex;2 J* ?+ Q7 ]$ v2 V$ N! C
        l_vaIndex.vt = VT_I2;" `6 B/ |3 J  a2 _! J7 N
9 |" ^" V0 V6 v# ]+ @2 o
        // 循环取得列的值
6 p9 p( z' a" C* }# }        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ ); y# T" d0 w3 I' @( l! ~
        {
* }; v8 W  f* ^! X! f" `2 Y) O# y            l_vaIndex.iVal = lIndex;4 N6 L6 C0 ^$ x, o2 B

! b6 C- q( X& {9 I            // 取得字段值
6 }: x" K. g* ?2 x+ \            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;: U; C  \) o# S( U" y: g5 ?/ b
        }
8 u- j! H# D0 w/ D5 ^        return S_OK;
. c/ G- j# ?9 H7 X  w    }; B+ H' Z0 C) C7 c( e/ ]- u
    catch( _com_error & a_pComError )- ^5 \7 G' u& N$ J
    {, R( u, x. e3 ?4 J
        …. // 错误处理
7 ~4 g/ q$ [# J7 @- d        return E_UNEXPECTED;
, E& |3 r& [* u6 G( _3 X  n/ @0 w    }
0 e% T4 s+ _$ z0 a9 d, C    catch(...)' p$ }% R$ o- e
    {
; Y. ]1 A% c: l0 j( F1 f        …. // 错误处理. e$ g! x2 i1 T, h8 }
        return E_UNEXPECTED;6 y; J( E1 H5 i. }& t4 k
    }3 ?, j* P6 \! |  d
}
+ ^* @) G# l9 w& N! r  G. X- q7 [# W9 q" o% d
0 x4 W4 r" _% q: d+ y* ~( k
7.出错情况下错误信息的取得2 w8 v) X1 Y$ R$ A" q

4 Q6 g) o3 e1 _6 W8 Zvoid ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );! n) l# k; T! ?
{) t5 c1 @( `8 ?6 k
    // COM 错误取得
' h+ @) V3 W$ x    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常5 B/ J3 G) O) C3 u$ f
    char lpComErrorStr512];
) x3 k, h  [# |$ a$ ^/ }% p- G# n7 m8 R
    sprintf( lpComErrorStr512,* g1 d; O6 O* q7 s! y. z
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",. d. J* B# E/ |
             pComError.Error(),                  // 错误编号9 i' u1 z! q  [$ Q. j
             pComError.ErrorMessage(),           // 错误信息
7 i' B0 l# h7 j( s1 Z" H8 R8 |4 r             (LPCSTR) pComError.Source(),        // 错误源
' e% F& q; y0 _+ {             (LPCSTR) pComError.Description() ); // 错误描述( F" n( G7 u9 m2 z- Z( Q

3 s. p* |$ c2 ]1 M' H- ]3 F5 r5 E    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
1 ^: q- n! G6 }& j7 k+ X6 {    // ADO错误取得& I5 t$ j3 f$ _; @+ P0 ~

. K- c7 |" v" g3 F% ]0 b    ErrorPtr pErr = NULL;0 |4 [: s  O) N) o0 T
    if( (ptrConn ->Errors->Count) > 0)/ p8 k) l6 `0 G1 o) W
    {
+ `3 i# M3 p7 X9 I- O0 g3 J  a        long nCount = ptrConn ->Errors->Count;( n$ f4 s2 E, D, \+ r. _
        for( long i = 0; i < nCount; i++ )
2 v! d: j  S, R( w9 x$ E, x1 m        {9 Z1 V# f& v4 S/ c3 a
            pErr = a_pConnPtr->Errors->GetItem(i);* w% S! o' U0 J7 P/ w$ b4 C! L. k
; k2 a. M+ t# D" o( y
            char l_pchErrorString[512];  U( {: F4 K* y, A: C
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
( T1 k( r, a; B) ?4 w  V7 g                     pErr->Number,         // 错误编号
- N! K( \1 W+ }" v* Q# C                     pErr->Description );  // 错误描述
$ `2 U: t: [7 V, ^        }
) [6 H5 _4 r, @; _" ?. `    }& c3 V5 S$ n$ T# `, Z9 X, T

& q3 s" F3 c, R; v* s; M    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问8 R: `5 ^( S& A$ K! {) k
    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 08:50 , Processed in 0.018688 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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