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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
# J: }* D: {: j8 P1 A, A2 Z* _! q! E7 {) t& E' h
1、 用import导入ADO 的 COM 文件msado15.dll  O+ b2 ]1 O* T# Z4 u5 a7 `) j
. O" b2 e1 }* M+ }* o
例如:
3 s. ~, m7 B2 e0 c. b  V3 C3 H. N( h6 _. F  x- ~
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\9 z* i$ S1 p' Y, h, V

" S; `/ w9 T1 f   no_namespace
/ A& x$ r' @: B# W4 @
, `' F. t9 y: `3 Z1 a- n3 z1 Z- G& n$ N6 X
2、COM 使用时初始化. s. ~  J$ d3 Z  G: r3 o& ^% f
4 {+ y/ t! k0 v2 q9 {; h
HRESULT ComInit()( m7 O3 O2 s' P! N6 `; b
{ 9 y/ ?7 {, a$ M+ O( f- j
    HRESULT hr = S_OK;             // 默认返回值2 k% g. K1 K7 c$ b
    if FAILED(CoInitialize(NULL))  // COM 初始化调用) ]) [& I# `, m0 y
    {+ s/ b; D/ r) b# q; q$ l' d
        CoUninitialize();1 w4 {! P7 [9 J- A3 P
        hr = E_UNEXPECTED;1 ?3 g0 F0 q8 D$ I7 K7 A( E
    }
' Y5 }- G4 w* \. l9 {2 ~    return hr;) f. o1 n. k# h+ C/ |* L
}7 [+ G. [- o. x( C) T& W" @: c
, e4 f3 V% S( ?: l, R

6 D4 |; X9 W: ?# V( x# e3、建立数据库连接" `: o: U/ d" y6 j: B6 b+ G
' F9 `5 t3 o( y% O  s$ u
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名4 [8 x% d- c4 l
                     LPSTR pConnString,                 // 连接字串 - }7 F* I- L& M6 }3 i
                     LPSTR pUserPassword ,              // 用户密码
) v6 Y. f! ]4 F# I' {                     ConnectOptionEnum ConnectOption )  // 连接参数" V7 J9 o5 m/ K4 t1 ]. y
{/ ?5 C$ E  f9 x4 h; O

. b' ^& n8 E( l. U+ p3 e6 M, l    HRESULT hr = S_OK;        // 默认返回值
+ a( E6 K1 w/ W7 O8 K    _ConnectionPtr ptrConn;   // 定义Connection对象) N, j3 j: O/ F

& o3 X1 B+ O7 N) n# X    try
! K7 p1 }( E8 Q7 K/ N4 v8 v) e    {
5 l! T$ |$ w( z8 `( z1 R        // 创建一个连接实体+ @! {7 c' O# g; c7 a+ i4 R
        hr = ptrConn.CreateInstance( __uuidof(Connection) );$ j) H2 X4 k' {# V' F

) S2 h: ?8 [1 H1 w  z6 |3 Q4 V        // 设定连接等待的最大秒数,默认是15秒8 s+ s/ [& ?  o: L& {$ m
        ptrConn->ConnectionTimeout = 20& }9 y& G( F' |2 r4 x6 O% a; s2 o

" T' P9 {" e8 {0 Z1 I0 e* j8 u) ]        // 打开连接7 M) b" w1 R% o' o: A: P1 i/ Z5 a- w( x
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
' h8 M% O2 ]! t4 ^1 w0 s) R* C! N        return hr;
0 S7 f* ?4 n, b4 k) S  O5 V+ ?    }
: ~+ k$ J* X& z$ `3 s/ q    catch( _com_error & pComError ): F2 R' o7 u3 y
    {
7 X7 i$ l5 e; v0 {5 n        …… // 错误处理
' r9 `( Z/ a& G4 p" T- j        return E_UNEXPECTED;
$ q$ v: ~9 S7 w* I4 K    }* m5 g: z1 {0 w0 i; f+ c9 y  y
}
) l4 j7 M0 a9 d# `% k; \3 b0 L: ]! c2 m4 `8 P
8 _0 x7 X! ?, I5 F1 |$ _$ Q
4.执行一个SQL 查询,得到数据集(recordset)
/ a1 n0 F& m# X6 N7 C
' p6 N2 o7 [. X& ]6 f8 q+ `% v& V_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )' J. _+ h5 L5 H7 d
{- ^0 d; T8 z; Q0 p
    try. k8 l" ]# L* k/ p
    {) M$ N. V* ]* G7 n  V2 A
        RecordsetPtr ptrRS; // recordset 对象4 b  V! j! F7 o

# x% Y2 W. ~5 J( p3 p& C        // 创建recordset 对象实体
3 F! s( Q* g" t* V# |        ptrRS.CreateInstance( __uuidof(Recordset) );% o, ]: _% {0 N# I; y! |
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
: Y7 s, ?7 p5 p$ vadLockUnspecified, adCmdText );
2 y5 x- L/ ]! ?7 k4 m: r- n9 f; x. H7 e
2 i# b% `; J$ G+ U' d        或者% x2 U" Z% F6 O, Y$ g% U
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );; I9 G$ s9 l* {( K8 S7 d! {
        return ptrRS;8 P! S* E7 G6 X1 p! A$ k- o
    }
8 S. B# B/ D" a$ d* O. ~    catch( _com_error & a_pComError )
' j8 G7 q6 L, }; y) E1 ?+ w7 e0 Q    {% H+ y: F* t. I: H# M0 |3 |$ p! Q
        ….// 错误处理
4 A6 D+ l1 K, Q+ k2 K1 R        return NULL;
2 g" k2 n4 Q+ I% C- u9 c- @8 q    }
+ z" E0 c% Q8 s4 X( B# H( w}
! H& n% \; ^! g0 W8 U
2 d6 M2 S, }8 p* b7 y0 K  e6 S; s0 E8 v3 ?3 V2 m9 d$ N8 q
5.通过数据集(recordset)得到列的名称
0 l. i" L/ _& k5 H& r+ m1 x/ X& @0 j& Y5 q  W' N2 O' m4 s: {
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象2 I$ D' l9 Y6 q; e' z
                        char strColNames[][255],1 ], J7 Q7 Q  S- q: C! b
                        DataTypeEnum iColTypes[] )6 P/ |6 V' Y$ z$ D" H
{
9 G+ L* M5 n5 x4 ^5 O" Z( b0 D    try
- Y$ P/ B7 S$ S8 L9 ^4 L    { // 参数变量
& o  Y0 j+ G) V0 m: m7 t        _variant_t l_vaIndex;2 z( ^5 G! Q; x  X& a. i' }

( G+ j5 }3 p) X        l_vaIndex.vt = VT_I2;
4 l3 L  B9 E$ n6 W- ?( ^, l, x" A4 h& x  Q0 e1 g! x
        // COLUMNS总数
1 Z* m- ^1 P" ]. L2 T9 F- _! n        long lColCount;
" f. a+ q4 c2 ]4 S
7 O/ ~( P! t/ ?# x        lColCount = ptrRs ->Fields->Count;
* K# i# Y9 c8 I& L7 O
4 T& Q" Y! I) Q( r, c8 d        // 循环取得列的属性和名称
. Y8 v. C5 i$ ]3 ^/ }4 k        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )3 y$ L! C  W9 Z. L; b3 d- w* |
        {  S0 r! X; w7 f( I2 t+ \, f) I
            l_vaIndex.iVal = iIndex; // 设置循环索引  R; l/ X3 O4 n5 |' p" V9 }

1 Y3 B" i  ^8 T/ E+ N% }7 l/ y: l            // 取得字段名称5 v7 g$ K& e4 A6 ~, O! |' e
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);" a% ]1 F6 b4 n: J7 ^
. M$ M7 H! S# M" l: z) [
            // 取得字段属性( H9 h5 M( y  Q5 H4 N: g
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;
0 G9 d0 n! s7 D        }- S/ v, u! Y5 ?0 b' A
        return S_OK;
& U5 [" P" D0 M5 s6 P" @8 T    }2 }7 c9 w" L  {9 L  H
    catch( _com_error & a_pComError )
% v- s' T: E6 _: e: F    {3 H3 H+ k; [* D8 J
        …. // 错误处理
# |* O7 O5 S& ~5 x: n        return E_UNEXPECTED;
: T  A6 j. ?4 t# b2 c5 T    }
) q4 C# a3 o& u    catch(...)
: ]. l3 \1 j2 u4 ]$ ^! o1 H    {# P2 J7 N; F8 F8 n
        …. // 错误处理5 Y  H0 k9 A( C( B; D
        return E_UNEXPECTED;, |1 b2 n3 y5 X! t5 E) q" V+ |, }' M" `
    }
- D3 }9 v7 g6 z/ o$ l! _}& v4 g4 o! R" O& O4 Q9 u4 Y7 W
6 c. [8 j8 a: T

! t6 ^& o( E0 J( w6.通过数据集(recordset)得到当前行记录2 k. z; @$ f( v# n( `

' @" Z8 j4 C' k1 V! b  NHRESULT getOneRecord( _RecordsetPtr ptrRs,
2 S8 Y$ h  Q; _0 s+ R                      const long lNoOfColumns,6 B. n4 Q9 k. O) B5 ^
                      _variant_t varValue[] )
# M9 U$ Y* K8 ], _: y& G{8 s% M# {  T; [3 i! N
    try
3 M, l$ ]8 U  b    {
7 P. ^% h8 A0 R2 d# W0 V7 n        // 参数变量
$ \+ B6 n+ T- Z! F        _variant_t l_vaIndex;
& ]. `2 |% |: Y& F7 o1 e        l_vaIndex.vt = VT_I2;0 b/ _9 e8 M& m" C0 T2 ^% k6 s; k& j
. B/ r5 G1 P- f4 Y( _
        // 循环取得列的值
/ L. f+ E& P0 p4 r3 w. m" E        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )8 X; Y% n- p7 ]
        {
3 c. E1 U- f8 l& `            l_vaIndex.iVal = lIndex;$ r4 B7 |2 z* b. p
: N3 a5 |. ]8 W
            // 取得字段值
  V# o: J2 o- I            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
/ l& V. d! q% ~. x; P' k2 i: {        }1 O' l/ L, A; y5 z! J
        return S_OK;: R; I; t4 Z" Y/ S; n* c# U  j$ }
    }
. Y! P: z' b+ L# v: u    catch( _com_error & a_pComError )
# [" s( Q+ t5 o, o$ H, L& c    {
, x7 s1 o9 {- N; v: }6 A' }$ U        …. // 错误处理
1 ]! `9 P& H6 S4 F2 y- {7 T' T: Z  C        return E_UNEXPECTED;
" L# v8 f# S5 A& b3 K    }% J! M6 i; \) Q& C1 r$ J8 z
    catch(...)4 N' \2 d4 {0 u
    {
+ ]( u- a% r, k  }( r/ ^" i        …. // 错误处理3 r/ r; k9 ?7 L- C7 _7 G
        return E_UNEXPECTED;
7 W8 a: M* q) M. p    }- _$ `# q! J/ c% t
}, s4 ~4 t# o  n+ R3 F$ \

1 u+ Y5 Z- e" N5 P! I5 |& ]2 A6 p6 X/ K8 `. r; f% t2 }
7.出错情况下错误信息的取得, E6 g2 n! F. t* t; o6 p/ m! R
9 i( {/ y3 I! n$ M, r1 Q
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );9 u: q/ z1 T; I3 k! j: n& a
{/ N2 g1 f" q5 v1 l+ L. C3 z
    // COM 错误取得
# ]: V, x: p; s$ y$ v% @% j    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
% Q5 |* O- h2 J! U; S    char lpComErrorStr512];* i$ N  a8 ]( N2 d- |) J
" W$ Q7 O1 i, G) Q+ Q2 U' B
    sprintf( lpComErrorStr512,
; p0 w% T/ F4 ^$ e- c7 T1 S             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",
) N7 {& u. Z4 G! ]& ?7 n             pComError.Error(),                  // 错误编号
, d" X6 E, R8 O  `# e( E: h& e. Y             pComError.ErrorMessage(),           // 错误信息* b0 n0 _1 j. D: o$ L4 t4 A
             (LPCSTR) pComError.Source(),        // 错误源
9 O) V5 B+ a; z$ Y# y4 l             (LPCSTR) pComError.Description() ); // 错误描述
% `6 O% {+ e. E! U- J5 y. e. d) P1 m. b) ~- q9 ]; i: p8 J
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
& f: {  v4 K# w8 E! U    // ADO错误取得
8 e" G' n0 z- q6 K7 [( s2 `. _5 Y( X7 r% |  P  n
    ErrorPtr pErr = NULL;! ~0 t( `1 W$ T' W) \" T
    if( (ptrConn ->Errors->Count) > 0): V2 ?, E; ~0 G7 o7 v
    {" B( C6 e8 j7 q1 d5 o6 H4 J
        long nCount = ptrConn ->Errors->Count;' j+ S4 |+ Z* V, `
        for( long i = 0; i < nCount; i++ )
3 o6 G- ?5 J5 y4 F8 C  b% c/ D        {, J  x4 A; e* I' P
            pErr = a_pConnPtr->Errors->GetItem(i);; @" i/ G; n& X, `! t
5 m! O* j- w' b- |) f8 @* S! Y" S3 P6 H
            char l_pchErrorString[512];$ c, a% Q+ o$ U% a, B
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
6 _$ A1 P/ a5 Q  {* k                     pErr->Number,         // 错误编号
. \/ s0 F: U, i, `5 c$ J& j: J                     pErr->Description );  // 错误描述
/ C% f: E: o* H* R        }- o0 O( A$ A/ {
    }
" f9 t6 X4 v7 p9 ~$ M4 B4 e: S3 T+ g. G" ]" q
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
7 S8 Y3 {* k7 u5 D7 _" F+ ^% n    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-4 16:50 , Processed in 0.019932 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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