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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
/ X: R' n) f% T! o0 E* l
5 g, t0 k8 [$ X  p3 Y3 m% s" _1、 用import导入ADO 的 COM 文件msado15.dll
$ z+ ~3 d" a5 P5 k2 t: u3 V7 d  O* y4 K% T
例如:
4 c6 \2 n' w5 l# k$ _. J6 S5 g2 u; O& }! K. _) n7 n3 K2 h
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
2 H$ P6 A% \1 J6 U$ J" G" T" n
+ ~' O+ F, |$ F# Q5 `- j   no_namespace& ^' d7 V" Q# v0 h# R# T5 k
# n& M/ n3 g+ u+ [# z7 |$ v
0 ^( S3 b7 M6 y- V) A
2、COM 使用时初始化6 ^, r0 I" O# j
  n( \9 Z' C8 }
HRESULT ComInit()5 x) [3 z  f1 h9 x  Q0 v
{ 6 L# u. f% L0 a8 D7 L7 Q; ~
    HRESULT hr = S_OK;             // 默认返回值
9 ~4 _* ~$ c" E/ M; d2 y    if FAILED(CoInitialize(NULL))  // COM 初始化调用0 C' G' W% H" U' F8 N8 |/ E
    {$ S4 y4 L3 Q, G4 H5 l
        CoUninitialize();% O) M) ]' r3 g" r
        hr = E_UNEXPECTED;
5 C- y2 @" [3 p& O  K/ O    }1 D" y4 q6 ^/ ~5 ?
    return hr;
$ N; T7 B3 @6 `+ V, w2 m% V: r}
1 c5 H0 G" M) ~! ?! _6 q& M+ k
3 G) r5 Y! U% n
) r& t! K) j3 V5 d9 R# L- W# o. s3、建立数据库连接
, ^9 g" D, f% Z' n1 z: r  i6 a4 |% g! Q% E8 t! P5 u
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名
( o+ Y; L  ?& P) X" D; a$ a                     LPSTR pConnString,                 // 连接字串 2 F1 M6 |3 K3 \& E+ o; f
                     LPSTR pUserPassword ,              // 用户密码
5 O& `4 U, b3 r5 _5 J                     ConnectOptionEnum ConnectOption )  // 连接参数* R# b. n3 l* {( `' w* Q8 B
{
0 C3 F" A! l$ ~
9 |8 G& x. Z5 U: J/ B    HRESULT hr = S_OK;        // 默认返回值
2 r* K$ G+ \3 G" E    _ConnectionPtr ptrConn;   // 定义Connection对象! P' Q' r0 I3 [% C

6 p( P" E4 ~. {( C5 x4 L: ^# d7 U    try2 X5 B7 L' K5 f7 W0 j, B- q
    {0 `% U# h8 r6 g% P
        // 创建一个连接实体% K" Y( x' f- |( ^
        hr = ptrConn.CreateInstance( __uuidof(Connection) );
+ j: d+ b8 x# d! L0 V* I4 y$ e2 d0 e' Q9 N
        // 设定连接等待的最大秒数,默认是15秒8 M' ^8 |  y4 S% k0 h4 u& ?" k
        ptrConn->ConnectionTimeout = 20) X* L" u2 K/ B1 ]' J) T1 n

" n, z" a. H; \" P# D1 S. C' r        // 打开连接
& w( `  ^* G- O        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
' K7 d: T8 k$ a8 q# @        return hr;/ Q3 B+ v  ^. \5 d) r9 _4 k( c
    }  r& V1 W* \3 W' ^6 B
    catch( _com_error & pComError ), C$ M8 L$ k0 Y0 r1 b5 \$ j3 }3 d
    {
8 ~" l$ k0 j1 O7 }( `1 u        …… // 错误处理
5 b2 I6 I. n9 F+ o- g        return E_UNEXPECTED;2 F4 b! y+ Y6 J0 X# G7 s9 o) x
    }
4 K: O% i* n- D6 y( K1 }3 G- ^}7 C! c7 k1 M) L$ K  _* D3 {4 _0 `
0 l  H4 A8 Z/ w- N  S6 }9 h0 s
6 {6 H' G: a6 s# ~& W
4.执行一个SQL 查询,得到数据集(recordset)1 }9 W! [$ l* G, {

2 [# y3 Q! v) I9 B; C_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )1 W& t9 _6 _  o) G" ?
{% d5 x( y1 ], o+ v
    try
7 z/ e+ _) R  z& L    {
3 Y! H- Y4 L* r' ]1 p7 I        RecordsetPtr ptrRS; // recordset 对象
/ b$ |% G  C7 L: H' C+ C- m( m: V
        // 创建recordset 对象实体) J" g) u9 }. Y, i
        ptrRS.CreateInstance( __uuidof(Recordset) );7 V' h) V, Y) @# C) c) \+ Y5 q
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
7 _# j: o) C* `& f9 k0 badLockUnspecified, adCmdText );$ r; o, A  O; T$ L7 B  W

* B( p  {) `2 _        或者7 q: A' v! Q3 |+ X
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
: v7 m) p2 H% b% g  y& D        return ptrRS;
* ^( `" e% w2 ]  u7 Z3 ?( @! a/ Y    }: Y* C; i5 ?( U, i1 w
    catch( _com_error & a_pComError )5 U# ^$ d0 }0 M2 i. @
    {1 [- |- D: H: e4 {7 C% L0 \1 r6 z
        ….// 错误处理
% k- `" b% g/ y! {, ^* Z5 F        return NULL;# K) ^0 @( Y% |$ `. O
    }" L( H4 y4 t) Q
}# l8 Q! K  E  n9 t! @) V$ t6 U/ d6 P1 H
& m; c3 V0 R' K0 D
* \3 C3 f8 i* J! P' S
5.通过数据集(recordset)得到列的名称
- f% f6 X9 ]" l- t4 \3 z* g" h  T* N. j1 B1 W  ?, y' {' p
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象, k: \4 D5 D4 {$ J
                        char strColNames[][255],, `- m& _* D3 I2 F  i  f
                        DataTypeEnum iColTypes[] )/ S% A# N! Y& Y' H$ ^9 ^
{; r' R% v3 a$ Z
    try4 G. _9 f7 i2 E' l1 K& O
    { // 参数变量; N$ O. \  B: A
        _variant_t l_vaIndex;
; c) H4 U, X# N* p3 D3 w( J2 g& z: l- [! t( R
        l_vaIndex.vt = VT_I2;
% y$ G2 m: @) B2 U
/ c7 l0 r" V+ T  `$ x        // COLUMNS总数5 F& Q  M- p5 z* D8 l: M
        long lColCount;( A8 L' j- _! u6 k1 z4 W2 m; [! Y/ ^* v
6 j+ |; D1 V) M$ e- h
        lColCount = ptrRs ->Fields->Count;
& \' G5 S2 C  ]+ i% S' |# ?9 [9 Q  @" \; Z4 }
        // 循环取得列的属性和名称
- A' n# R! {- {, B3 E        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
  \" k# c; I8 B3 T/ a4 A0 j5 P3 I        {
8 L+ _" G+ w$ ~3 f8 ]            l_vaIndex.iVal = iIndex; // 设置循环索引: U1 d$ q# F, ?! G; K

7 q  ?# s+ Z2 [+ s- @9 @# H            // 取得字段名称% X5 C% y: @# |" ]# {8 i; Z
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
5 ^: O/ o+ h# @4 E* S$ ^2 [' M9 Q; {8 Q3 l' d/ |
            // 取得字段属性5 p) e' S& H' w2 p$ [9 B4 n
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;- F/ T# M  r# e4 T4 S5 C
        }9 T& b2 L( U3 A0 a! h) Q" P
        return S_OK;. ^1 Q7 n8 J7 y' u
    }
+ y4 e9 m) T: C# v6 x0 }    catch( _com_error & a_pComError )
% I8 D& J+ L; {- V    {5 ~" R  U2 E! [( A
        …. // 错误处理
4 i2 l7 S% N) F1 l/ w( b7 t: h7 u        return E_UNEXPECTED;* {5 ]- f( ?9 H* {! R% \( a
    }; k2 {9 q0 L. T* F, m
    catch(...)
" Z- a6 x2 S; j, w    {
9 M! {& v; G9 O& V- ?$ E1 k        …. // 错误处理
- Q) X' T) M* l$ p9 g        return E_UNEXPECTED;
" j( {: i' w) H" d8 u    }1 C2 a! c6 C, R- n3 w: Y0 F! g
}& \- u9 ?7 ?1 [
3 _3 d6 ]0 A. n8 a

4 O# ~) G( ?1 ~- r& H$ R6.通过数据集(recordset)得到当前行记录
8 K5 }; C5 e- |8 Y9 q. H7 m3 I5 M7 x5 |5 o8 N! k) @
HRESULT getOneRecord( _RecordsetPtr ptrRs,
: R# H4 u# O* m4 |2 l# i7 l# a5 d                      const long lNoOfColumns,
  _8 W1 w( P: K- Z                      _variant_t varValue[] )
, Z( o8 q  {' w2 l# d{
: E' j  F- B; q! v. ]# B; J, j  S    try. s, n, X& J$ D( c' n# g5 R
    {8 W9 b0 Q' a# J9 A, ~, u# T
        // 参数变量
# p& w, }! k8 h8 |3 l+ \        _variant_t l_vaIndex;7 P! d( o* b" y% o* m
        l_vaIndex.vt = VT_I2;/ l5 m* v" U9 n- a6 `9 d

% Y0 u# \, }+ E8 G9 Q1 S2 j, x        // 循环取得列的值2 ^6 a, M9 r3 R) e: {  A' N( X
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )5 Z- ?1 x6 m9 z' O" \: G4 P
        {
) R5 `6 P6 R0 S' K/ C            l_vaIndex.iVal = lIndex;
& C, Y, ?# U; z1 p9 h9 E7 T4 W2 P! ~0 p# f+ R  ~
            // 取得字段值: J" f, P3 Y% h" T4 ^
            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;' x( }- T7 N" e: a5 D
        }
4 h  x$ t% H7 W0 ^# f$ ]. K        return S_OK;1 e. X! A2 |1 S
    }% y" u2 F# y- H( j' [
    catch( _com_error & a_pComError )4 G0 o- l# u6 {# a
    {
* n& F, }3 [* \5 U9 C- x( l        …. // 错误处理
0 A* @* N* G/ k0 I/ R- j% e        return E_UNEXPECTED;0 l0 _: b' O) R2 o- V
    }
, Y5 M( o, ?8 V. m5 J) n    catch(...)
8 {$ \  [* a% _    {: x: u& p: y2 n( l% X. S; s
        …. // 错误处理
& f& ?+ T" g' ^5 |        return E_UNEXPECTED;
( d1 s1 o( \9 F* S& s    }
# N! L9 w1 T% U; `! G. y4 H2 b}
5 n# e1 x5 X- I% B2 {$ J- C& e4 j& m( W9 D( J4 r0 N6 g3 q& F

) r, u+ o( A: B1 |% B1 ?$ p& l7.出错情况下错误信息的取得9 R! p0 \& y, Q, b  k( W" T% s
  M* Y8 X6 r  {9 y0 ~
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
; u9 R' p  j. H3 G{
% ?1 b: n) J! g& H( |( J* R4 H5 E8 g    // COM 错误取得
: _: I- i. y+ z! B) @    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
' A# E( |* B( Z' y( ?" ^, ]    char lpComErrorStr512];. K7 y' v# L: K+ [$ m7 ]/ {7 Q
8 M8 b, P( V4 Z- R6 i
    sprintf( lpComErrorStr512,6 H3 O$ p  U) R6 V3 L, `/ r/ }6 G
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",0 |' f: W* I! O+ S; z; j
             pComError.Error(),                  // 错误编号! F# n, F$ H$ d
             pComError.ErrorMessage(),           // 错误信息
. ~" u% P! w' V* w             (LPCSTR) pComError.Source(),        // 错误源
8 P! m9 T- I4 C6 S9 k/ C             (LPCSTR) pComError.Description() ); // 错误描述
! C: z- k3 r' g; @, I
) W, p/ W4 R5 C7 Y8 }( k2 Z    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
5 t" i8 @: q" u5 d: U6 S    // ADO错误取得
' j# v4 b/ L$ R) c
& [! \; E1 z0 D' S+ J# c! D+ b; ]2 D    ErrorPtr pErr = NULL;
( W* z" G8 v; F9 Y7 _4 y    if( (ptrConn ->Errors->Count) > 0)
1 {' g2 a' d) N. Z& P$ g    {2 Q- A# n7 y3 R5 z1 c3 v
        long nCount = ptrConn ->Errors->Count;& O' d" T* k7 G
        for( long i = 0; i < nCount; i++ )1 P3 ~( O) m' E. B+ w7 P0 `5 E( `
        {
+ d" z9 P% @4 x2 X7 n1 _            pErr = a_pConnPtr->Errors->GetItem(i);- Z; l% c4 }  B- ?0 V4 a

8 P' M" t3 p1 o3 q' \; X' u. y, C7 h            char l_pchErrorString[512];
# ~7 P+ L! n6 r            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",, _9 F2 l8 _2 {* F& |# H. c* S' w
                     pErr->Number,         // 错误编号3 `8 z; T( h2 a2 g7 X! V
                     pErr->Description );  // 错误描述
3 O( x, t6 a7 {! ]        }) S3 H9 E! d7 {# k6 |
    }1 X0 g* @1 \3 |5 ]3 l/ n

6 V( H: k% o8 `, @) N    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
0 T+ `+ L9 H, X. A' a# c  g% Z    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-1 23:11 , Processed in 0.016149 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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