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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
6 @8 H9 O# F0 Q, |9 ~( X% o" V5 @# ~+ r+ Y- f5 U1 r0 F9 w; i# g
1、 用import导入ADO 的 COM 文件msado15.dll  i6 p3 w% X0 H: `9 w
: j3 N9 o8 i9 t- F% v* Q
例如:5 ]2 N, r) M8 h+ Y6 U0 U* A" Y/ X
( ~) Y- [7 j. f4 o
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\* e) w6 s. c9 {

: s! I' X7 \( L. }   no_namespace
* ^  y  ]% a4 P/ K9 Y4 ^
5 D6 y. H( i  K" b, [# H: u4 H! R7 L/ E$ I1 d
2、COM 使用时初始化4 a) W5 o0 S1 r% E! R# C

- v' f9 Z3 A* E: J8 d# QHRESULT ComInit()! H% Q6 N' _" O) J% V, x2 [. j
{ 2 |# Q3 |% I! \) L1 u; N$ ?
    HRESULT hr = S_OK;             // 默认返回值
: b2 _0 v2 R* R7 C1 U7 b3 F+ k    if FAILED(CoInitialize(NULL))  // COM 初始化调用/ A6 ~/ ^8 C' ^- d4 X! N
    {
4 A$ T4 P* J+ R5 F9 C5 Y        CoUninitialize();2 g: f8 z9 c0 b2 c
        hr = E_UNEXPECTED;* u6 M3 u3 N' Z% s) p$ \
    }
' s1 b9 y! H7 I! d    return hr;' q0 i5 R9 M6 v' O: p4 n+ h" V( ~
}; F$ h8 l* t9 h9 }$ X0 M2 X" v5 E
( L" G+ F8 G) a. T. F: s/ G- s
/ O( g1 X0 U2 R6 S5 h8 x
3、建立数据库连接+ Y: v& \. G$ D& T, c) n" E$ x

, o# v. ?$ g% I: S9 @HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名8 A" Y' Z9 E$ w9 K
                     LPSTR pConnString,                 // 连接字串
* N7 I* j$ Q7 f# U1 A$ f5 s2 q& ^' A                     LPSTR pUserPassword ,              // 用户密码
5 m/ K; c  Z( E6 k9 ~! h, D+ T8 y                     ConnectOptionEnum ConnectOption )  // 连接参数$ R; `4 i6 B/ d' G( G3 f* A, ]- e
{
: h" b. Y2 Z) R' Z9 u, E4 }$ c
0 h4 n3 z8 i3 ^$ `: x& l* M0 T( l; e    HRESULT hr = S_OK;        // 默认返回值7 P" r0 H9 O: N0 l! P, B9 g! `$ ?* g/ F
    _ConnectionPtr ptrConn;   // 定义Connection对象
$ d9 d" ^2 j5 w' S5 H
" r) K- T4 p6 C" {  ]2 J: [    try
, Y8 f  [2 G$ F4 o! P4 Q9 w& n    {
) t' ^! k% c- o2 O' A1 Y7 Y' Q: ^        // 创建一个连接实体
( X3 T7 e( B- H+ c; n        hr = ptrConn.CreateInstance( __uuidof(Connection) );7 P3 ?7 b' v- t! V

0 G% U1 g  T; e% Z8 D# x        // 设定连接等待的最大秒数,默认是15秒  x, }- R7 j5 H7 v7 a4 Q' E
        ptrConn->ConnectionTimeout = 20
& T2 b8 o* U* B3 b9 F$ k
1 F4 s+ u. y" S, h2 a4 I        // 打开连接
4 I: t+ \+ Y% ?% Y; x) l# }; ^" f6 @+ t        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );6 S# N+ d+ h3 E
        return hr;
& v$ I9 h! W7 q1 g    }: h. E) [+ O. r; P* Z
    catch( _com_error & pComError )
# Q' \( a# {+ ?* Z6 C, \; c    {; o$ T8 I# N1 B( I
        …… // 错误处理! Q( E$ H$ e2 B2 V
        return E_UNEXPECTED;8 v: C0 A7 K: B  d7 G4 l( }
    }! ^$ X! o2 f* |: b/ [: U% K- U
}
: }  Y5 U4 f! y0 [0 t* o; ^" ]* g' Z0 Q6 y  h4 [2 V
8 A4 `# v( l1 B* I
4.执行一个SQL 查询,得到数据集(recordset)  K2 y& Q* Z1 B3 h/ d8 z+ c

1 w6 t- i8 G+ ^; ?) F_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
. Z& G! H9 n. n- Y6 `{$ K2 Q4 v* D7 q; M
    try
! e0 [. k9 D9 n8 d6 z# a/ s. A4 `. G    {, R8 Z8 b  [, ^
        RecordsetPtr ptrRS; // recordset 对象
* O" ?6 p; b0 p" F' M1 u4 \. S4 R' E1 C. J
        // 创建recordset 对象实体
6 }3 c6 q* E: a+ J: i) W& P        ptrRS.CreateInstance( __uuidof(Recordset) );
6 W2 K/ O9 ]$ E3 m- j: z  W+ W* H, q# _        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
! {. {3 R, w7 T& s# s* r% radLockUnspecified, adCmdText );
8 s1 b+ N$ {9 H/ r+ H4 p6 [" ^0 t" P
        或者) M2 i8 G. ~- f6 g
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
, d9 O" {1 j# i2 I4 J        return ptrRS;3 A) C' j( B; I- J8 [. Q
    }- X6 [1 e0 H2 x( V: ^
    catch( _com_error & a_pComError )1 \, Z" R% V* t
    {
5 q6 |7 q- h: c        ….// 错误处理% B% k; B+ M& E, n  V
        return NULL;! \, b( X/ m9 V; h, Z) X" X# a
    }: Q" E  J8 R+ j8 T  x
}. N3 y; g% r' C) K
0 h& g# e. g: j
$ s& d$ M/ u* w: k2 |! N! e% C
5.通过数据集(recordset)得到列的名称
# j- ?* D) Y1 Z1 l4 m7 ^$ Q6 u7 a4 n# j
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象1 l; m& E) L. x) @- ?( O
                        char strColNames[][255],1 ~# ~% ?8 M) f0 ?
                        DataTypeEnum iColTypes[] )* u  j* H+ i! G' K5 I8 B
{, L- z& e  U, x" d' `( e
    try
, \" }' k. M. O- R3 ?    { // 参数变量" Y- A$ J8 @8 j
        _variant_t l_vaIndex;
: n+ e( O$ h3 b- J1 q( B' z! h. m# u8 z. p& E
        l_vaIndex.vt = VT_I2;
% m3 C5 v1 x5 a
- k$ N, l6 \. p/ T        // COLUMNS总数- N. _7 W; T; n
        long lColCount;( s2 y" A9 [1 ?. G& h, j) \, S
% M. v: g  z7 Z+ `1 j
        lColCount = ptrRs ->Fields->Count;9 g1 i- g. j+ L
7 W2 z* ?  T; K3 M% T6 l7 [
        // 循环取得列的属性和名称
( i4 d1 v  }; B( i/ h) t        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
$ Z6 Q5 X5 n$ `8 u        {: v8 [! c5 i+ A
            l_vaIndex.iVal = iIndex; // 设置循环索引
4 O* l& B1 [2 x8 f' p3 |+ l) w3 I$ b- D* v  h
            // 取得字段名称: Q' `1 x# b+ k$ m  N
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
) R$ e! J# p/ Z# I; S
3 x1 R# Y& z/ ?& b0 c% S            // 取得字段属性
# x8 L' ?4 X  \. d) w% u3 `            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;* e7 A& q# {; C, Y
        }$ c. ~5 ~8 V4 x1 W' d$ i$ Z1 Q2 w
        return S_OK;6 q: \7 u; \5 C; g  t
    }
; E% A7 I9 \8 N; v; u% e    catch( _com_error & a_pComError ), R0 }0 ^1 {' H" H. t' |4 V  |4 L
    {) N; h* D( J- s) }7 T/ e2 e$ k. J
        …. // 错误处理5 H& A" l4 E" ^  \
        return E_UNEXPECTED;/ w* f0 q" `$ |% r% a; J8 m
    }/ z6 @$ Q  f$ w4 {
    catch(...)/ P( n' y) D4 W; X/ Z1 v/ \
    {; S/ [9 w  F4 `" f6 C- l
        …. // 错误处理0 p$ m  D# t% A; Y* B4 Y  L5 M8 Y
        return E_UNEXPECTED;
( M* F, V" i2 f7 R( `5 L. B. k, r9 R    }: l! t1 O3 F8 Q+ D7 E" H' G8 A: ^
}* ~; e$ y/ D: [; M7 p6 `( b
- K4 s+ M; B: A: d: j  l. N1 ^( m

3 [. Y' E: U, d" Q4 e6.通过数据集(recordset)得到当前行记录
, z$ F& |8 b6 u! X
" s8 U" `/ V' n# vHRESULT getOneRecord( _RecordsetPtr ptrRs,+ i& T+ ?# d" E( a
                      const long lNoOfColumns,
6 r7 h0 [/ `! ^* D( [: h* X                      _variant_t varValue[] )
9 K$ N1 \/ ?! g. x( H{
& S3 h4 V  C" m3 {, D3 s+ w. q    try; T; h) Q. F6 p2 |
    {, s+ b6 X/ c' N
        // 参数变量
8 A/ B) {; X" m; T        _variant_t l_vaIndex;
6 I/ X5 f0 p, D! a1 D! F! r& m/ v        l_vaIndex.vt = VT_I2;
7 [( s" Q9 Q# ]$ T& G4 W5 ]* D$ ^+ ]" V8 @
        // 循环取得列的值) J9 K# |' e. Q2 z
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )# p2 g% M, d8 U1 B# S6 J
        { * I) |2 h- U; l% j4 j9 \
            l_vaIndex.iVal = lIndex;* K5 i) D( t2 u3 p. K

2 t* J6 J: g7 d  A7 u9 }            // 取得字段值
) ]9 A. c- c3 L2 f, s$ @+ i            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;2 A1 P; e( y/ I' j+ b
        }6 {2 y' f8 [1 E& L+ n  ?
        return S_OK;! G+ F) J& S5 w! A
    }
% \/ u* d  O3 O. U3 i: b6 t    catch( _com_error & a_pComError )
" ?0 Q8 E% y1 x    {
/ f0 I* x* n2 E7 n7 W( ~0 f- c        …. // 错误处理
6 t7 ]; z) Z' p+ E' D9 s        return E_UNEXPECTED;) W$ a. x+ s0 a, W' k# d
    }: d+ I6 n8 B2 `3 m& s2 S8 x
    catch(...)
# x/ ]1 x  X- w2 m' d    {, X" ~1 r9 l4 c2 G
        …. // 错误处理7 G  d' v. N! J6 b% L
        return E_UNEXPECTED;
1 F7 T& R1 f; s, Y    }
$ {8 O6 ^7 t% o  y2 R$ f, [}8 n0 h- m2 O1 f1 O2 m

$ s/ Z+ ^! K, \) O8 ?! }4 }: n; O2 r% `3 C- [2 B- q& I5 X
7.出错情况下错误信息的取得1 m* C6 @( q9 R

, h/ v/ G% f* Q! ]& Z4 }void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
( J" s3 S' o- H5 L{# y/ a/ `# }1 C' R5 g
    // COM 错误取得3 }3 ~* j( B: J) M& s. ?
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
6 _5 u6 O& Z; A' T: @5 @    char lpComErrorStr512];1 {+ j* B  p! i# O. Y  Z

$ t6 l0 d& ?3 }5 I    sprintf( lpComErrorStr512,% S3 L; s- M; x6 A; y
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",, m; s$ F  \' D4 _- ]/ Y4 q  ?, g
             pComError.Error(),                  // 错误编号
1 ^* K! ]5 P% A) S7 x4 c! c5 u" ^             pComError.ErrorMessage(),           // 错误信息
  {9 e! x" n$ D) d" S  ]$ R             (LPCSTR) pComError.Source(),        // 错误源3 n+ K* V8 a% R' S2 M' L
             (LPCSTR) pComError.Description() ); // 错误描述( u( k5 N6 n$ B9 P
( k4 T" d$ u: D: u" |* B+ m
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
5 y5 R& b3 E7 U/ L8 s    // ADO错误取得) b2 Y) o% D& p/ u
7 E% z- w, P, i
    ErrorPtr pErr = NULL;
6 D" {! {& z5 O# \  M    if( (ptrConn ->Errors->Count) > 0)" X1 r& |& ^$ ]  K$ E: X8 h
    {
7 C, h; u7 u) @* @1 w" T4 k        long nCount = ptrConn ->Errors->Count;
: I6 W7 I& g. G/ }, n  N. C0 {        for( long i = 0; i < nCount; i++ )- G0 c% T' j* E: d0 Q1 p
        {& e! z& h% g1 a5 b( h, k2 k2 P
            pErr = a_pConnPtr->Errors->GetItem(i);) ]) ]: f' s1 }% z! l4 I3 ~- B

( v9 T! |' E" i" V            char l_pchErrorString[512];
) K3 s, U, ~3 |  B+ d            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
9 M( {- C/ P9 N$ _5 z' h, X( V                     pErr->Number,         // 错误编号
4 |8 E( ?0 _& X" p                     pErr->Description );  // 错误描述0 ^0 }0 Z4 U" ~$ B* X! [
        }: M! @: r! e7 `3 s- s4 N2 ~- U
    }
2 O/ Y' X, l: Z6 N9 g! o# k: V% h7 ?+ z* q) `
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
+ ]$ N, H6 V* l2 k$ n  t    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-9 01:49 , Processed in 0.034594 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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