找回密码
 注册
查看: 4608|回复: 0

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。& l8 X% z- A. H

& t( W2 e7 u( \0 [- r3 ^4 z1、 用import导入ADO 的 COM 文件msado15.dll2 G5 r) j9 z9 y2 `, w& P+ g
; i- P; _' _9 q  |- p# g1 K7 l) v
例如:% t( o7 F+ F6 L" r* ]1 Q

2 v3 t5 b* c, e/ M: f2 U  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
7 ?# T( d8 ~! f  {# V. x& o( R' _
7 N4 u/ Z9 [5 Z' i" i* S   no_namespace  r) y8 y- w/ G9 t( {, y& B8 g" J
6 K' u, l: ?/ D1 S4 e, W
3 s" }6 ?# e: d; P
2、COM 使用时初始化
& D5 D4 K5 C: E( C4 V: q8 T' \5 E+ G3 b3 U, M  B  Z+ `1 j
HRESULT ComInit()2 L! \( M9 _6 o8 a
{ + [, J$ U. [: k( s; t3 o
    HRESULT hr = S_OK;             // 默认返回值1 i- I$ ^% \3 i& z" p, E3 r
    if FAILED(CoInitialize(NULL))  // COM 初始化调用3 o. A) ?) e) b" e- l9 |
    {
4 f! w' s+ _- U# W6 R, N3 y        CoUninitialize();" {: Y4 x! M+ }' s& T7 m
        hr = E_UNEXPECTED;
+ b1 o! e. e- {/ P6 H0 D4 O    }
9 j& x" Q6 M# u, N* M4 z9 Z! Z: w7 f9 Z    return hr;1 T+ F( A2 O0 c% |
}2 n( h% a5 Y: n8 }0 X! A- G
* H! T  m( f! h% @

  W8 Y" M, k7 ?& g0 l: B3、建立数据库连接' N: _+ W- T3 @" B

' {% ]6 M9 x4 a1 l* |6 h6 d5 AHRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名
& V/ T5 a& w% C; }                     LPSTR pConnString,                 // 连接字串
$ I; P8 u; k+ r$ S4 i                     LPSTR pUserPassword ,              // 用户密码
1 v7 Y$ ~2 Z! E- }" Z! p7 S6 z  q                     ConnectOptionEnum ConnectOption )  // 连接参数
* X7 ~- Q; G; I( r3 l& G{) _" E0 s: _5 O1 t1 d+ }& S
; {! f' p9 j0 |
    HRESULT hr = S_OK;        // 默认返回值
! A$ x3 r# E) u: G6 K8 K    _ConnectionPtr ptrConn;   // 定义Connection对象! f) E7 E& M! E- T

: ^7 W# _; U* A* v+ o    try! Q3 h- s9 e/ V3 O' M) V  k9 G; e
    {
' k1 ]& N: X2 V' X9 h. I1 P        // 创建一个连接实体# O, @1 U( r7 n/ P5 s
        hr = ptrConn.CreateInstance( __uuidof(Connection) );
3 N+ ~; v8 Y0 j: d% b; C) E0 u) x9 N( }( r  a1 L0 v
        // 设定连接等待的最大秒数,默认是15秒
2 A  {7 Y% i: j        ptrConn->ConnectionTimeout = 20! c# v6 m) Z1 Y2 z8 x! ^. q  ~
! u6 U( E3 b( E2 u1 p+ f) z
        // 打开连接
6 E6 P9 J/ @4 }" I& ?; _        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );' P- p) P* l, N& X: I3 D
        return hr;2 @& n6 Y1 v% Y( c. m' J
    }
% `" D& l) \6 a0 _# v6 t4 I    catch( _com_error & pComError )% w) Y' W$ c% T7 }& k/ S# S
    {
/ E/ ~5 o; H. U. }' Y# F: [        …… // 错误处理  ^* }) _  z) s3 n- G, ~
        return E_UNEXPECTED;
' E3 ^9 h& b) S" ?' ^    }
" P) h8 o# `% Y}  Z3 Y" G% {: o8 h1 o. \7 i+ I% A! c. Q
8 @6 s" }4 f" e- W4 J7 a% l
9 A3 t! ^+ l3 j5 _
4.执行一个SQL 查询,得到数据集(recordset)( i. Y2 T7 {3 z3 M% G# C

% }3 y) o+ D2 G3 R_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
: ?$ A8 x. m2 {9 M5 A; H6 z{
6 Q2 c) r7 w" `2 l5 s, r% ?9 u    try: m9 s. Y' j. J# t
    {
* r6 S* Y: W4 z+ h0 E2 a3 J        RecordsetPtr ptrRS; // recordset 对象
3 f. q4 n% R2 W! x% q) z% N6 a) A7 q8 b/ m0 P  c
        // 创建recordset 对象实体/ {# }& H& }  B0 @2 r+ X
        ptrRS.CreateInstance( __uuidof(Recordset) );% p, r# x! @& C1 ^
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, 3 r+ F* `% f9 H6 @% b8 _
adLockUnspecified, adCmdText );
' R" Z/ {% E) Y# T6 o% t
1 C3 c7 G7 c5 B. W3 H        或者% W/ M! i# F- z
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );' Q! C4 L' W% i' R7 m0 ?. W; ~
        return ptrRS;
" @* {' u# d  H4 L9 Z+ o! z: x3 h    }9 k4 j, k8 u2 ^1 J5 Z
    catch( _com_error & a_pComError )4 E1 A: w& `% Q! q% w* r, q
    {+ ]1 A5 Y+ N& \% a& `- C0 e/ F6 J
        ….// 错误处理
& K- O$ h6 e- P' Q( w  A  i+ i: f        return NULL;
! ^- A& p7 e9 V8 `    }
; N0 l  N& L* x! u}2 i  G( |" A/ p7 ]# s. F/ Q$ @

. c' i5 B. \# L- M- Y. `$ E  c' ]+ p9 N
5.通过数据集(recordset)得到列的名称5 O+ g! D. Q; x1 w1 G
/ ^4 g4 L+ ~$ t" s$ f* F5 P0 V
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象. c4 J8 d1 A6 \" g
                        char strColNames[][255],- a3 Z; T# \( q7 w% ~
                        DataTypeEnum iColTypes[] )9 f" v6 S3 D5 O( I: i" v# F9 I+ ~
{( {# ?, c* Y$ c) I8 X# u
    try
( X8 y. }: S% w* l8 ~) @    { // 参数变量# T/ b* P7 k# p. r3 A4 \) [/ w
        _variant_t l_vaIndex;# n4 `8 d6 {/ t# F

) M& Q; Y# K1 `' g: e        l_vaIndex.vt = VT_I2;
4 Y0 I# z/ Q+ n4 i, b' R+ c( [9 {8 v: g
        // COLUMNS总数4 L% v2 ^. F" s; o2 y3 I) A
        long lColCount;( q  f& |) A8 w+ I: j0 l

0 |- z$ |% n1 t: m/ G1 H3 |# e        lColCount = ptrRs ->Fields->Count;
; }3 ]  M9 ?2 S9 ^, G. G- [; j/ t# x# D& q# x8 f
        // 循环取得列的属性和名称, O; m& R* z6 m' X
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
0 r* v8 [7 Y% n2 F        {8 _( a$ T+ {; @
            l_vaIndex.iVal = iIndex; // 设置循环索引6 m/ [% o6 Q  @3 x) s: z6 |9 o! |

7 F' f! {. N" i" N, x            // 取得字段名称
* H& M: Y. u+ W0 p3 ]" X            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
" M0 k: k2 U5 @) ]1 K, L! T3 z. W) J* Q7 A! K* K+ R5 ^
            // 取得字段属性
1 E+ r( W' ^- j* k7 \8 M            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;
6 P9 ]/ C- H6 i( F$ z5 i        }
  j1 Q5 T; o& |        return S_OK;
, K: m0 d' \! V7 x$ V    }
7 D, W' N7 {+ J2 L    catch( _com_error & a_pComError )1 K+ A% M# ^. g* ]
    {
, U8 T) ?3 ?8 C        …. // 错误处理( {2 e" d9 N5 s  o. [: q
        return E_UNEXPECTED;
9 `# s8 q  f7 d    }0 C) \: `) K1 R& q5 G
    catch(...)9 B9 w+ r7 ?, b
    {( ?8 |8 p5 I: M. d( O
        …. // 错误处理
, n6 K7 N" D% s2 J9 R1 k% u        return E_UNEXPECTED;
8 d( N; f8 D8 q; @1 D1 W    }% u& ]: m6 l4 N0 V& J
}/ l; a2 q& t3 x3 B: W8 L% d3 {

! W- `' q& Y! B
' g5 w4 W" D# |9 n3 v0 `6.通过数据集(recordset)得到当前行记录$ e& j- h: O4 Z0 s0 ]( D" v

2 L% r/ T  u# @3 qHRESULT getOneRecord( _RecordsetPtr ptrRs,
- u! ~" H0 ]( n  {7 Y                      const long lNoOfColumns,
/ Z* ~' b; G0 @* V1 S  J                      _variant_t varValue[] )
$ R4 G1 U: m7 l* x$ K{) N; K3 b4 Q; f" c
    try
" G$ I8 x4 Z$ F4 G! i6 j$ m2 E) r    {. j1 h9 Z  P' O6 ^4 l: u
        // 参数变量% _: Q' r; K9 v1 ]
        _variant_t l_vaIndex;
  I$ h3 N) p- [& k8 @2 B        l_vaIndex.vt = VT_I2;! K; s' {0 E% g# s  z! h
7 x. @2 M3 Z0 U$ n: g$ j; Y5 c
        // 循环取得列的值" f* I! G7 g' J! O6 B& J* |
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )
2 I6 U: V' E5 Y7 T1 j        {
: W4 a4 o. ]1 r            l_vaIndex.iVal = lIndex;& Q0 h% e+ \/ i. L  ~  |: w& L1 c: p) ~& t

' x. v& k, m, x! S4 x            // 取得字段值
$ Z( W' h' Y, b6 i* d& j            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;; [3 x; x) {4 H  d
        }6 E% ~% p3 B% K) c7 P
        return S_OK;- N6 a3 c' E, b( N' n6 z5 s
    }
0 D: F  A$ f  l2 ]7 |+ A$ w    catch( _com_error & a_pComError )
5 W. n! E; `( ?3 l4 a    {
2 _6 `) y. X4 o) `. l3 |- x        …. // 错误处理
9 A' s$ h+ X! g& @2 E        return E_UNEXPECTED;
2 W: t9 {: ^' U3 N( y' n( C    }
$ Y' w- k2 l+ D6 X9 F    catch(...)
/ H6 D& G7 W5 u+ f; ~# d; N    {
& `* e# q; k# `4 A; l* V        …. // 错误处理5 V. E4 i) h; S  j# J$ G6 T
        return E_UNEXPECTED;
5 ?9 ]1 c4 X: X    }7 K# F6 c0 a  R7 r. X  ^+ u, p
}5 ?$ h5 o3 ~8 b  |& a/ j& D0 d
& }( f( `2 @. t7 N' m; Q
( V9 A; p! [: w5 o  x
7.出错情况下错误信息的取得
; g9 D$ `3 X5 o7 R4 P: d
) w' _& q& I( E" p1 ~8 xvoid ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
5 a. S+ m/ @6 [5 E- l{% o1 x* l5 J1 Q
    // COM 错误取得& U; w7 \' S9 q: m
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
* C0 |$ a0 g0 u! c+ o: ^    char lpComErrorStr512];2 h. X5 p# }5 ^& k8 Z: w2 u: T% c
+ z5 A1 w; P; U" u; s
    sprintf( lpComErrorStr512,
& a3 I- @1 v4 D  _3 r/ J! {5 Q( q2 x             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",
0 X9 r4 _; j0 z; X+ D/ o; i$ C             pComError.Error(),                  // 错误编号) W3 r# c& o9 E
             pComError.ErrorMessage(),           // 错误信息
( z8 t. D% n& r: e( w* X4 s/ v  c             (LPCSTR) pComError.Source(),        // 错误源
$ |& N  Y% @0 u+ J, o             (LPCSTR) pComError.Description() ); // 错误描述
# s! D% V" [7 {7 c+ s0 l
7 M. \( f5 z1 j- t/ C% J! g; u    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息+ D! h4 G$ [/ d. }; v8 `7 \
    // ADO错误取得
, g% [- q! F6 B) s3 X: f) t: q  ?) J6 C" ~
    ErrorPtr pErr = NULL;2 U" d# g' f* l2 ^7 v
    if( (ptrConn ->Errors->Count) > 0)+ Z4 W4 B8 c0 z& I6 O+ x! G! i
    {4 _( Y- E% N& Q+ q' J+ B0 s+ Q
        long nCount = ptrConn ->Errors->Count;
8 _3 p+ G- r. b2 J. [( g        for( long i = 0; i < nCount; i++ )1 }$ s. p0 M6 B$ z
        {
9 A3 r: e# ~0 U. G8 c. V& [            pErr = a_pConnPtr->Errors->GetItem(i);  w! a+ t  C1 ?* L) u
/ [+ e2 ~0 e$ q$ K( j
            char l_pchErrorString[512];
4 g* A4 o7 i# @8 D            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
% U3 P- i" J/ @8 a( h7 I9 n                     pErr->Number,         // 错误编号
4 J. ]8 R$ J. m2 k* r/ q! ^2 W                     pErr->Description );  // 错误描述5 O4 `0 a2 |2 k& \
        }
6 T- |$ \* V1 r% t    }
; v4 n; a" K3 v8 U7 w7 i, u5 f- B6 t5 M2 D" }; u( }
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
# U; p4 S6 s/ |# J$ C    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 02:37 , Processed in 0.018301 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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