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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。  k- s% y4 {# ]6 h, S% }
0 S4 Z" }$ I5 {5 s
1、 用import导入ADO 的 COM 文件msado15.dll& K0 E  m; O5 T; W& @3 Y5 F

. u. S9 @& e4 m1 [4 P例如:
4 p: l# g# ]' ]. n; [: |
3 L: L* e7 `! W  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
$ t% S/ e  {; j; S/ V- [: l
9 D# G2 r+ u/ ]5 G/ S) V: V( D   no_namespace
  m' h1 ?/ q. {' r. o0 z# {/ C( O  O- Y7 F1 F/ p/ W- e. }
4 D9 t, G7 j, W) s8 c. e5 M
2、COM 使用时初始化  Z2 B, N6 f$ H+ _, l% n" k  X) n
* w# Q2 w0 h' P: K+ v* G
HRESULT ComInit()8 [7 `4 X/ s6 D* k5 s
{ ; v. _5 n% t8 V3 Z7 x) ?2 O
    HRESULT hr = S_OK;             // 默认返回值
3 r7 @9 v& {' ?* f; Q" G: {4 o    if FAILED(CoInitialize(NULL))  // COM 初始化调用: P9 ?0 p% w- g8 s4 H" t& N
    {9 d8 c* l8 `* X8 B
        CoUninitialize();
: B, Q' N" X4 @# z        hr = E_UNEXPECTED;! z+ a2 B' B' x) I1 Q, E
    }
, q( u+ y  b$ J- V    return hr;1 t8 V" {; }" c8 B, s
}
* [0 m3 Q" x3 p$ Q/ B' x- \# V7 s+ ^# c
" Q. b5 H! J+ T$ L6 ?+ U4 N
3、建立数据库连接) R+ j. u5 ]& a# r
- p9 I. E+ Y$ H, d8 ~% S
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名5 M- J* D- i/ a0 |6 z. M1 T- D
                     LPSTR pConnString,                 // 连接字串
! g  t8 E' [, _) }% a  `8 J6 R                     LPSTR pUserPassword ,              // 用户密码0 [1 M) N. q8 `/ v5 z
                     ConnectOptionEnum ConnectOption )  // 连接参数
4 n! C1 E: s; B2 ]" k{
+ p+ ~6 r5 O" z) U# {8 Y# _4 o( W4 E8 N! f7 g
    HRESULT hr = S_OK;        // 默认返回值  |3 U; U! w" n& r3 z$ ]
    _ConnectionPtr ptrConn;   // 定义Connection对象
+ c7 m5 W( K0 i) z: a& R
1 {  e/ {; K# o( q. m& d    try
- u' u' o& ~4 o  q    {, J6 w0 |! h8 r/ f: l2 r
        // 创建一个连接实体
3 K* {) N7 }: P* t( X! c        hr = ptrConn.CreateInstance( __uuidof(Connection) );
$ M- I4 w+ K7 r( l5 \
# A* Y: B6 P# C, u. U% W        // 设定连接等待的最大秒数,默认是15秒! [$ r" S6 n, g' d
        ptrConn->ConnectionTimeout = 206 B; ^4 G' t! Q% {. J; X$ J- A
3 q3 p1 l5 p8 u& ^* R. O# s2 z) T5 P
        // 打开连接1 I' m; f8 }/ q/ y! v. h
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );9 p4 |9 D0 A& ]6 Y
        return hr;
" q  e5 [+ O# V6 B    }
0 \8 P2 m, L& `0 N, D, G    catch( _com_error & pComError )& X, j5 \( c& K0 c2 |5 K3 q
    {9 G, J4 Z  S7 c) c+ D
        …… // 错误处理& ^8 n! d. Z/ N) T: w5 n% k
        return E_UNEXPECTED;, H. z8 _1 d4 |$ Z
    }; {6 ^% \) w' p
}+ ], A2 G- K! ^& w) E, n# q& b  Z( B
4 e4 k* s8 B* s' [4 H  @+ x
2 W& T3 C2 ]. A  l# [
4.执行一个SQL 查询,得到数据集(recordset)
" E( Q6 B' W7 F- K3 ]- f3 P+ P
) V) b% i0 F" Q8 a_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
% ~$ t/ r/ m9 P, N7 }7 ]* Z{' m  ~7 j. q  U! @$ H
    try
$ W! z6 Q0 y5 D& K9 d2 t* a    {
" S" ?, i# e/ w0 L9 X        RecordsetPtr ptrRS; // recordset 对象9 q: K% L$ c4 b: s( s$ {& Z3 [
* {8 _" T" L6 V. V
        // 创建recordset 对象实体
! e$ w4 C+ @/ [7 N        ptrRS.CreateInstance( __uuidof(Recordset) );# j$ L0 `& K2 U2 }8 i8 I
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, ; w0 i% M- T2 i7 n
adLockUnspecified, adCmdText );4 U9 I7 ^% `1 Z) |- c

' L( Q1 B) O/ Z+ v% h$ i8 V        或者% S1 }0 o! I  M# X. q
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );3 X# c. R. M5 W
        return ptrRS;
7 z) M6 h* n# N& t6 `6 ?; D% b    }( L4 l, H- @  d" ~4 t
    catch( _com_error & a_pComError )
4 B" c% q) g9 M    {
0 C6 [* M: Z/ t( I        ….// 错误处理
1 K: Y, c+ N5 y+ y5 H2 F+ F        return NULL;
: X+ |# S9 o( b' E    }: E/ @2 }. V, k. z- W. _4 O
}
( u+ r( f5 e# Y" A7 n
: ]$ s3 [0 _& s; ^. s8 r3 ?; E+ f9 {9 ^" `/ I2 d
5.通过数据集(recordset)得到列的名称, M% {) N- E3 ?9 U
+ w; R, B$ P2 w
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
% R3 x8 [, S( q1 D  L5 T8 ]2 C                        char strColNames[][255],
6 W0 O/ K( Q$ i* O  U, G                        DataTypeEnum iColTypes[] )2 c) X& x/ K$ [0 {) t( v% G5 ?
{
3 [( P# r* o* I2 W    try! j1 T4 V$ ]5 n6 v
    { // 参数变量* W1 D- Q! M, W5 v1 H2 n8 _
        _variant_t l_vaIndex;
# d3 u6 N$ P/ D5 n/ C+ d7 [
/ y; w; @1 \$ Z3 `9 J# @& m        l_vaIndex.vt = VT_I2;1 \6 J1 t  J$ e$ f' k: Q; f) o

9 H1 R# W5 {4 ?: f2 G        // COLUMNS总数$ j6 F$ Z! w5 F' p& g3 B- n  J
        long lColCount;
6 {# I  |5 ?' o3 N- n9 f1 k! D3 V. C6 v' E" Y- P) R5 a9 Y6 A
        lColCount = ptrRs ->Fields->Count;
5 P" x" y6 _/ B0 Y1 ?! _: o$ \- S2 W& `8 V: {0 y$ W' ^
        // 循环取得列的属性和名称" z3 o% @2 F. x: G
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )$ E, l8 N# D8 t  Z) j! J+ J1 ?
        {
& z4 s6 X  W5 v" K            l_vaIndex.iVal = iIndex; // 设置循环索引! t% z6 E# [& F2 G, f
5 `# G  h- O: j
            // 取得字段名称( j! I0 \( k  s, D+ X
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
2 b% {% x8 z3 g+ e' a. b! }8 N1 l% m5 r8 [$ P- i1 _! {
            // 取得字段属性# T  L5 v+ S  t- [' @
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;% Z$ s8 J! G% k9 |: @
        }
- d- z3 a' U- G/ S        return S_OK;% d+ B8 c# g$ N# {( ^; Q7 E
    }
3 y( b4 s  h1 O( \. S4 e, {    catch( _com_error & a_pComError )% B& j# D* h  T7 k0 ?8 @
    {
7 Q5 k% D- \$ ?: {        …. // 错误处理; R+ T. c& @" B
        return E_UNEXPECTED;
& C# o- `% K  f3 ]    }
1 @1 ^6 M; P3 ~3 Q! @( a    catch(...)( i9 _: @$ f! o( H% h, n
    {% b# ?4 [6 L" \- Q! f" t3 i. V) r
        …. // 错误处理+ i+ x" m1 y2 O& B: k
        return E_UNEXPECTED;& T. }' A: E6 A- D5 c
    }! p* x: V; ^& D2 i  U
}! E. H- O/ \( d  A) I

/ D' p* n; n$ v4 U* D% q! ^
) U; K  |8 F+ k" ^( n6.通过数据集(recordset)得到当前行记录
5 D, p3 l9 \' c1 N
0 y8 [( V+ ?: W7 u' tHRESULT getOneRecord( _RecordsetPtr ptrRs,
, M. J7 t! ?+ {" c% [) p, e  G- }2 y8 \                      const long lNoOfColumns,# e3 l4 l4 S+ @# D, Q
                      _variant_t varValue[] )
4 Y1 g; g+ C0 N( ^6 ~. l{; @- s1 }% g5 j7 {8 D- W; \
    try
8 Y4 `2 Y: U( F& B3 t# e# D9 K    {  q0 }- h, L/ A  f3 ]0 H
        // 参数变量) r. A/ ~0 _- x/ t
        _variant_t l_vaIndex;
) G3 J# I0 D( G$ P) W/ r        l_vaIndex.vt = VT_I2;/ C" L2 t; B" g- J) ?

+ p9 g* m6 M; C) p4 a( S        // 循环取得列的值' P7 Y0 F; s5 n0 E4 h
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )
* F/ U5 {4 |0 y3 G$ X        {
; L8 m% k! ?* B$ Q            l_vaIndex.iVal = lIndex;
) j* a% V8 f0 q, y/ c* ~' s3 F7 ~
! L; A% k. M8 S- e            // 取得字段值
; U# W4 n6 X, t* M+ R5 Z% `7 T            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
8 v4 J/ E/ b/ E* q/ E        }
5 G' c- d7 I3 K  F        return S_OK;
3 m, a2 o1 `* Z. e, L& W    }
2 w) m7 _4 R) j! }% R- A3 y" a    catch( _com_error & a_pComError )
- p1 c9 e( G) i; s  t$ t- d    {
" d  |) W$ q! L4 S; H- t3 `        …. // 错误处理
  u$ m' t& S, B* P4 ~% O) V        return E_UNEXPECTED;# r& G: Y  c2 c  h& o3 o& _1 |
    }3 @  a5 u& ?, k) B& I! j
    catch(...)
. O$ R. |2 {- [: p/ y& \1 V( D    {/ T2 l2 Z) p1 l! \. O* `
        …. // 错误处理
5 }, ]1 C. h+ Q! G% |0 u  }        return E_UNEXPECTED;1 f: ~5 }0 ~  E7 s: v) J
    }
; P+ M$ Z7 M6 O1 ?$ q- p}9 D7 j2 B" e" `* u$ w9 Q, R

: w, b7 \: a; x4 u  ^  @
& _+ {" ]. n( X% @( l$ n9 X. f* l7.出错情况下错误信息的取得
7 A4 s) `* G3 b  _5 `+ s# F! x+ s" c; ?& [8 t
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
2 ?* E/ P; H8 l{. [7 O- o0 t* W( d3 [
    // COM 错误取得
& S" B$ ?' l  x5 U4 U    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
" W3 J  }* ?0 u/ Q( @# }" j- b    char lpComErrorStr512];
7 e: G. @4 K0 j4 F: r0 T; J+ L/ t. a6 b5 Q# Z1 _
    sprintf( lpComErrorStr512,  }; a7 u8 \% J" w( r+ H0 i
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",
1 H" t0 x+ y# C( K9 {9 A# a1 w             pComError.Error(),                  // 错误编号3 b4 Z" Y0 @, X  w
             pComError.ErrorMessage(),           // 错误信息8 ~) F) z1 H3 s2 x+ I6 a) l
             (LPCSTR) pComError.Source(),        // 错误源) w- P3 Q( z* [. [: q
             (LPCSTR) pComError.Description() ); // 错误描述* c( N( H  W4 g6 g% k* H7 T5 b

) N" R7 U" \/ @/ U' e3 j    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息+ h& b5 n3 o7 B" V( g
    // ADO错误取得
$ U1 }5 \# y( ~2 ^: O# D
4 Y) z$ q- V) f* j    ErrorPtr pErr = NULL;
  A( M, c  E0 i4 d6 h    if( (ptrConn ->Errors->Count) > 0); i9 q! s! r: B" m) S7 x0 P
    {4 ~7 V$ F' o0 j) _
        long nCount = ptrConn ->Errors->Count;
! A: I: K1 b2 o" B3 \. q9 z        for( long i = 0; i < nCount; i++ )* U5 q1 c6 B, G, C$ ?% c
        {
, L2 Y% o4 E* C: t            pErr = a_pConnPtr->Errors->GetItem(i);" s9 Y0 \( o2 {! ]$ V$ O3 N
* p8 @' {7 Z, T4 H% ^3 w
            char l_pchErrorString[512];6 U* E: P+ ^" C) ?8 `, ^; y# a6 V9 ?
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
& `5 O; M! |  g" k1 S6 N! K  c                     pErr->Number,         // 错误编号
2 r) _6 s& k* z( \% B, `3 w7 b! q                     pErr->Description );  // 错误描述
' P+ \+ g+ _, J8 _6 m0 o: Q( q        }
3 c3 o+ I6 C2 u8 Y3 o    }
# c. {- A  G3 @1 c) S/ T$ P" H: t) d, L* N) D2 o6 {! N3 d1 s0 f4 Y0 M
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
. Z7 _! s" d4 z) m1 Z& @8 N- [    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-15 06:20 , Processed in 0.017135 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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