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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。. ~2 O. z8 m5 e0 T
7 p. H$ P0 r, |/ |
1、 用import导入ADO 的 COM 文件msado15.dll
7 y# M8 E# N9 M. M5 {9 Z  {2 s8 H! T
1 l8 L. ^* P4 U+ A% n% d例如:  i; _! Q2 d; x( r

! @- B2 M! s* I# A- l3 {; K  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
7 _- C/ f6 D0 b+ a( X( e  X9 V) d0 L, T
   no_namespace
* E( m7 H: C$ E; P: y) J- d' P. F0 b7 R! D5 N3 Q. A4 Y

3 E' }( u1 s1 G2 T+ F2、COM 使用时初始化0 \/ ?9 n1 v+ J+ k; t* n& V

6 Y& M5 y( J# q, u( l7 I& iHRESULT ComInit()+ x: d6 r: a9 S+ Z2 g6 G! |
{
1 M$ h% h+ d# j    HRESULT hr = S_OK;             // 默认返回值
- k! R: @) P3 v1 [6 F% l    if FAILED(CoInitialize(NULL))  // COM 初始化调用
' ~! h8 J# ?8 C9 G. t% h* v/ X, Z    {% o& M4 z3 ?5 K
        CoUninitialize();- u0 `% q, u# ?* G. S
        hr = E_UNEXPECTED;, d0 @0 F0 A- w  {7 J
    }
, h% H' L2 v- S1 Z+ N    return hr;# c1 |( ^1 `/ B$ i- t
}! d- w: L+ P8 O* B4 J* I- c3 X* a! A

: _- v7 W# P) v6 \% \
# L4 m" }+ ^/ u% _& D3、建立数据库连接0 B* w! [! P, r  A7 `

- ~# O  W2 k8 l. B- a6 kHRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名
8 R" x& w) `2 X" o: u                     LPSTR pConnString,                 // 连接字串
6 m3 j1 d5 A" Y" \' }                     LPSTR pUserPassword ,              // 用户密码
0 _6 X1 j4 H$ ~( P6 |' q                     ConnectOptionEnum ConnectOption )  // 连接参数2 I; j1 T3 j/ R3 v
{# }$ E. H/ w+ ^; h  q! q

9 ^  z# j8 R9 n8 P) V( m, o6 i! k    HRESULT hr = S_OK;        // 默认返回值
9 h& w8 ?- ~4 g+ {! X+ L    _ConnectionPtr ptrConn;   // 定义Connection对象+ e) o5 ]. z. j3 {3 `( }0 S

! w1 t9 J9 Y: y    try
0 Q# C0 n% O1 k/ h9 r    {
* b4 A! V1 O/ Y$ z; g! B' u+ r; _* y        // 创建一个连接实体8 k+ f8 V$ u  {# H5 E6 t
        hr = ptrConn.CreateInstance( __uuidof(Connection) );
1 |" d) B& a3 p0 E4 J* w! P5 U% k* C" i6 L, O' L! v
        // 设定连接等待的最大秒数,默认是15秒
  [# G- Q: |9 o+ J# X) p        ptrConn->ConnectionTimeout = 20
( B0 f5 E" z6 u) o" a; N: G' A2 O  W% Y
        // 打开连接
) F6 m9 j" N: g- r4 N        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
* i" O+ }6 s' D  r        return hr;& p/ B6 P. e3 V0 b8 @; G
    }' _3 K* E5 P; D2 @- g% ]* f7 [
    catch( _com_error & pComError ). p  ?# N0 {  M
    {
. R" ]7 b( K* B+ n4 ]        …… // 错误处理
; M4 P- Y; E/ A! C7 ~  k        return E_UNEXPECTED;7 `; E2 {& f( P! W7 H. Q
    }4 S  \0 ]- S" Z% j
}
4 {0 A8 a* S$ N
' _& g2 Z9 `7 G$ k1 ?! S& @8 j* v' W$ L; f
4.执行一个SQL 查询,得到数据集(recordset)  J7 j' l  N  D
5 t4 U2 g% y% M& s, o
_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn ); M! Q; v; s2 D
{
5 }0 G# q2 f6 F( x0 h8 Z) Y    try
5 M2 `+ d4 x4 h1 y# r    {
: u/ q& S2 B0 V1 i  M        RecordsetPtr ptrRS; // recordset 对象9 w8 ~2 w' I) t: n1 S* y/ w

& i! ]3 J1 ]) _        // 创建recordset 对象实体
5 E1 O0 W/ ^) a( Z# n" z4 Q8 a% `8 r0 P        ptrRS.CreateInstance( __uuidof(Recordset) );
9 j. l2 Y# ?: p# u        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, $ r1 @# K# G$ V/ z/ x1 E6 }
adLockUnspecified, adCmdText );
1 C, `  L2 \2 ~" z. I
, g3 j1 `8 p, z6 T2 o% H; h# i        或者
% S4 O& {- x  j% _2 N( Z        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
5 V( Y& A; R+ y$ S3 e        return ptrRS;8 j, e# X2 V8 j0 v. B
    }
, x8 w0 Q, k. s. X8 d0 }    catch( _com_error & a_pComError )& P3 G" V0 C3 m
    {
; U5 H& ?& b& b9 W        ….// 错误处理
% R7 |- T/ g( Q8 V8 C& r        return NULL;4 L' S6 f) [) U9 T! I
    }
; m" X- P- y' A* R, `. G2 r}
, s& d' ?- K( U( @: S
2 V* V. l" T5 w/ s! U' @& |4 W
0 S2 G; E$ s, a8 M5.通过数据集(recordset)得到列的名称
2 k# n3 |9 a' i
, O8 S8 x" E1 C& mHRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
8 e. ~* Z  ?  L2 V& s8 u  y                        char strColNames[][255],
% S, r1 s/ I5 z                        DataTypeEnum iColTypes[] )
" t3 R. A! }- g4 c! w{6 R8 t8 n8 @2 b- z/ r
    try
0 X0 a; _& `/ N/ C    { // 参数变量
1 Z# R- x. s& F& @* n        _variant_t l_vaIndex;! Q8 i' n" F$ l4 g8 ]1 d7 U
! n5 W1 R* N, D8 z/ |
        l_vaIndex.vt = VT_I2;
9 ~7 M6 Q9 F1 J( G* {, I7 q& N2 p6 c2 S+ ]3 @: ]/ H
        // COLUMNS总数
% M' G% y. t8 a6 ^' _& o& `        long lColCount;& y% P; }1 G1 F7 ?3 W
( m. I9 R, ~, i
        lColCount = ptrRs ->Fields->Count;0 n6 T6 R% \- [% [

( m7 K3 J. ^, P+ C6 `: d: q        // 循环取得列的属性和名称
, F+ x4 f! S/ K0 j0 E4 R1 g        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )( _% D- k4 h: m
        {9 h4 W* V7 K6 `* x
            l_vaIndex.iVal = iIndex; // 设置循环索引
# B- x! t4 u+ G1 a4 f# P4 @- Q* D6 Z
            // 取得字段名称' I+ s/ Z+ W4 V4 l8 p4 B! P
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);  {, i7 N4 |8 i  O: Y

- b5 M$ O, K" p' s+ L            // 取得字段属性: T* K- h4 W$ j0 D9 t# f
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;4 O1 R# ^. P6 f! G) Y) y5 V7 m
        }; l) m( j% w/ L5 k  R
        return S_OK;1 {+ s; _, v. v. H. x
    }
- D. C9 n7 B" _3 ?    catch( _com_error & a_pComError )' D8 }# e# r/ h5 ^& E
    {# s% c  n3 n( O6 w' n
        …. // 错误处理
7 a5 x7 @. i1 ~9 H        return E_UNEXPECTED;
! g: C# C1 P( p- ]0 ]9 L& O+ [    }* u% t6 J; R2 i6 i6 C6 [: C* Y
    catch(...)
  m. n( k% ]9 Y% X    {' H/ ~9 H8 I- V2 h+ j
        …. // 错误处理* m8 O0 B% A  s3 P! _
        return E_UNEXPECTED;
1 r. R5 R. t% ?. f! s8 k    }
& W5 Y! G" G  B: ^/ B4 c}% X) R) G8 V: x# G( J& B
0 x! M# P7 O! }# Q" J7 N2 B
$ B! L: U0 H0 V: {3 }- U' v: u
6.通过数据集(recordset)得到当前行记录
1 f) d5 c: W2 j/ d6 a
  H4 v0 P5 C" H+ y  q1 }1 h" {HRESULT getOneRecord( _RecordsetPtr ptrRs,
5 P" t) L+ o- K+ N4 c  e1 [+ a1 h                      const long lNoOfColumns," l0 p6 {& B2 t: J3 {
                      _variant_t varValue[] )% k' ~; r0 C  N4 }
{
/ V5 m4 M- I, Z& M4 x    try
0 Y/ F$ w# D) q    {
( m: j3 G1 F  D( Y" {8 K        // 参数变量/ H6 H+ ]0 I3 V! a
        _variant_t l_vaIndex;
$ U9 W! N+ U0 O& w+ C) O1 g4 ^5 ^9 u        l_vaIndex.vt = VT_I2;
* M- f/ h3 |' o8 k. \- n; G7 ^  P, c  c. T7 X* ]: p) U! n# C' h
        // 循环取得列的值+ U# E0 @; ?6 o3 z$ m
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )8 ?1 a+ X, G, w/ G+ k
        {
4 h7 g5 n6 g  s" U            l_vaIndex.iVal = lIndex;7 j8 J7 q6 \4 o+ Y/ ?* M7 C+ A

, V0 _5 C+ E! F) @$ U9 t0 a& V, R- h            // 取得字段值
" C% b3 c' a6 j            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
6 @, K, y) g! B2 S# s        }
1 u& {1 H: }! J  }, n        return S_OK;
5 v! T9 n- M3 d3 d    }
9 E- w/ \7 j6 {  V$ s+ v% t    catch( _com_error & a_pComError )
, e  s5 s' \. A0 o! }    {" _+ Y' i* ?2 N6 C' A4 F* [
        …. // 错误处理
& W" V% G7 S8 p. `        return E_UNEXPECTED;5 X, h1 n9 y+ O$ m/ h
    }
5 G: m; A! u" n) Z; E; j( D2 }" w9 Z    catch(...)8 x. ^) b+ A: Z" E+ ~' d
    {
, w' I3 W  A9 `; v( g  r7 N" h, ~        …. // 错误处理
. G! I+ S( q1 H9 K        return E_UNEXPECTED;
0 w/ C( l- b& M4 `# E' D    }
' J# g" _& u0 l" m) c+ p}6 S; s# j1 {0 \

( B6 k  _! X! [/ i- p
+ M1 \+ A) H- v0 e6 j$ j7.出错情况下错误信息的取得$ Z5 B; y* z) a! s$ R- i2 N2 s
  S! |8 R  P% `% B
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );/ R! m! z7 Q/ e) c- ~# o, J
{7 S; N+ P0 J) x8 o5 s# f
    // COM 错误取得
) [* j$ S: r% ^- z5 y6 D    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常3 h# U' j1 u. d! w
    char lpComErrorStr512];6 c" e9 \4 w! K7 Q: f2 R

( W" T1 K1 g1 z: f, A    sprintf( lpComErrorStr512,
) c9 Y# |9 ~- p7 `) ~4 \             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",$ z' B, r$ R% U4 S, p& _; L& Y
             pComError.Error(),                  // 错误编号
( o- Q# r' h8 l& R             pComError.ErrorMessage(),           // 错误信息
) ^7 h8 a+ d; i; t) z4 }# h             (LPCSTR) pComError.Source(),        // 错误源0 c: J- c8 u5 g" e
             (LPCSTR) pComError.Description() ); // 错误描述
/ k) f1 J- v) T/ _; q+ ?0 [, o* }6 ~- _6 g5 V
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息1 F3 X7 ]5 ?. }) W/ K: E3 C
    // ADO错误取得! R! D, W0 L) I1 P# |% v

1 I' m2 |4 [+ f  r6 r1 g    ErrorPtr pErr = NULL;
& h0 Z% i: L  Z    if( (ptrConn ->Errors->Count) > 0)
; ^# w' a3 H6 i  l- t    {
6 ^& t% b9 b  M& g6 R6 l        long nCount = ptrConn ->Errors->Count;
2 }! c0 p- `$ D* b& N        for( long i = 0; i < nCount; i++ )8 s, V, o6 ~& m. ]4 X1 [: J: H* C
        {
  E" X4 T) f+ n6 k3 h1 {            pErr = a_pConnPtr->Errors->GetItem(i);0 X$ j) Y  w$ \" I3 ?7 c

/ Y& Y7 j  z6 T" k* c8 x            char l_pchErrorString[512];
' k# V& U0 E& e            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
. U6 k3 Z7 G% ~- Q% P+ V                     pErr->Number,         // 错误编号8 B# l% X9 i, c9 }0 x( t4 E% p* t) @
                     pErr->Description );  // 错误描述
& Q4 F/ h% G7 j" ?! ^, G, y        }3 O* m: _4 f& f* Y5 V# K
    }" y$ f( F* ^$ ?
( ?6 Q  F, @4 |  b( n
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
7 J# @+ I( ~. \4 a& u" W# E1 X7 C3 t    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-9 04:20 , Processed in 0.034895 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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