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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
( q% Z# w+ |2 k" Q  Y2 m: ]+ @) u1 I+ _5 Q% g+ Q8 R9 @6 `
1、 用import导入ADO 的 COM 文件msado15.dll
$ \; i* n8 l& W/ `  j/ L/ q+ c. b! J! |3 ^( X
例如:
- N$ z) B$ G/ u1 p% o4 @' Z. v( b: O- ?+ K# A4 [
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\5 J/ g/ G0 p  R& z% w4 ?

/ y$ u. E9 M4 G2 v- `   no_namespace5 R0 O: Z6 J3 v3 S

4 P- E& {0 F) z3 I8 }# z* V" b. k2 B" b' N: i5 x
2、COM 使用时初始化
/ o1 b7 B# t  c+ J9 P: X8 [& P) W) r
HRESULT ComInit()
: s: n: k/ d3 N; o{ 3 r9 R% I- @6 ~0 Y8 P& L
    HRESULT hr = S_OK;             // 默认返回值
. c# ^0 h1 Q, L: [. H    if FAILED(CoInitialize(NULL))  // COM 初始化调用( I$ n9 E, J5 E
    {
0 @: }; l" g3 Q: j  L        CoUninitialize();* i7 K8 }" O5 P$ I! E
        hr = E_UNEXPECTED;  E6 K+ z# ], _6 c
    }
0 h& e9 e. X+ i3 r* Y8 p0 A5 h    return hr;
! _* q/ _% g7 e0 x! }}
7 [' q  g2 u, \6 P+ u
8 a5 K- P9 v2 q) m" Q9 Z( L1 ?/ u0 i( O+ B
3、建立数据库连接- V6 M& A3 W: d3 q2 R  v

( C- z9 u' M( K/ n+ p5 jHRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名
* Y) o. }: F. R9 ^( h                     LPSTR pConnString,                 // 连接字串   |+ ?+ N/ `* r' K# l) E( r1 I
                     LPSTR pUserPassword ,              // 用户密码! c# A! v$ r3 x2 ]" V! I+ o  W
                     ConnectOptionEnum ConnectOption )  // 连接参数" E* P1 C" \8 `7 y  O0 l
{* E$ p3 d$ d3 r! K; C9 y

1 _7 P# u2 {# h% R& C; _  k    HRESULT hr = S_OK;        // 默认返回值2 H  Z8 T1 y& k+ t! s4 ]9 f! U
    _ConnectionPtr ptrConn;   // 定义Connection对象
' i& S$ \% @2 e. p2 w; b8 z
, W3 ~6 \6 X0 j% n    try+ [/ s* S5 d. R* S
    {' Y* w4 d" l& _8 P1 J
        // 创建一个连接实体
; h- P/ y* }  a" G2 C  c        hr = ptrConn.CreateInstance( __uuidof(Connection) );
6 n: n: n4 _/ p. d. A! U( F: B# K- S$ o0 o+ t' G& w
        // 设定连接等待的最大秒数,默认是15秒6 Z* a/ Q, D1 [
        ptrConn->ConnectionTimeout = 20' U: m* f  ^9 F. d' H

  b! p& o5 X, |$ E( [- H* y        // 打开连接
% @% H% O: Z+ D8 Z        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
/ E% ~+ h" }" H        return hr;
# R! H. C; Z1 r5 o% N; @3 ~    }
' ]* l% u  ?9 A/ ^    catch( _com_error & pComError )
" l1 ~- d! _5 o* A    {4 D8 S# W6 I' X( m4 [' o1 t- R" x
        …… // 错误处理. y/ r9 L5 S7 \) Z, F. x
        return E_UNEXPECTED;% Q$ P- ~/ v+ B' q/ |  l
    }7 U' U. @9 W& W, O- T
}  U0 h6 O0 k0 w- I1 w; q8 _8 L! G3 X  @
/ K7 `6 i' }* v# \
7 N0 j1 @* F! |" S
4.执行一个SQL 查询,得到数据集(recordset)! c% r8 v3 t. E+ K+ G
2 y3 U3 ]3 Q5 V) J
_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )' z9 P  a% M) L9 a1 G; F
{( q% V# m% F, E0 |1 X- q
    try' J+ K; z; v3 s9 A( e
    {
/ p) a( P0 u$ i$ u        RecordsetPtr ptrRS; // recordset 对象; ^0 b, Q/ x0 W

& I# K1 ]" p) O& T$ v7 ]) J        // 创建recordset 对象实体
9 y7 X& Y4 r/ J! }( n# L        ptrRS.CreateInstance( __uuidof(Recordset) );# x5 {6 ]3 M# f* c+ H+ |7 w. ?* ]
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, * w9 |, R8 ^) G' X+ ^6 K5 o
adLockUnspecified, adCmdText );
# X& Z4 T* s" g
3 X' k. M: A3 j# K4 q' z4 B7 E        或者
' ~- L5 |: o$ h% V: l8 I& j2 D        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
8 C% G$ x- L) K0 [7 H        return ptrRS;
/ D8 w! c( A0 |+ _  H5 u& c2 G/ y    }/ M0 _( K# z" r1 N# j
    catch( _com_error & a_pComError )* J$ d- A; o# Z6 H
    {
" H! D* J$ `0 o" h2 q8 x        ….// 错误处理4 y5 `# X3 }- Z& ]+ P6 o
        return NULL;
+ b0 ?: J# X# N9 G/ p    }
# _# H* [( J. @) q* x}
" F; P# @2 X4 v  Q( p' g2 S" s. f" t. I+ r8 o1 A3 h

  }* _% O7 i6 @: t# {% m2 {% z2 ^5.通过数据集(recordset)得到列的名称1 t" J. z. M" F% j, H
& L1 s! [! P* }! B) P/ z$ j* X
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象4 F5 J3 Q" `0 c/ j  R- Y  g
                        char strColNames[][255],. f4 e  q( M+ ^8 ]
                        DataTypeEnum iColTypes[] ). e1 e0 W# y' {# Y* x( m; y8 i  L
{
* |5 H  U8 Q$ W6 k+ A    try
" `7 u" @3 z% d$ t5 Z2 ?8 m# s    { // 参数变量, C3 n, X7 C, S4 A* `
        _variant_t l_vaIndex;, J5 s0 S$ j2 T2 G: [  i' d
, e  e+ \* a' e* `& ]+ Q
        l_vaIndex.vt = VT_I2;6 X6 S: Z7 J" {

* ^" ?* C! U" \        // COLUMNS总数
* z' |: V( M4 @        long lColCount;
( ^7 X/ ?. J  O' R* w, S: X/ W+ h" H! a' F& M7 V- d4 G1 _3 A
        lColCount = ptrRs ->Fields->Count;
2 y: B9 B, A- Q1 j: @' l* z- Y. w) @. W$ A5 W
        // 循环取得列的属性和名称
, {. h; L$ {- f) E( s; z  O5 D* k        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
2 j3 }# N, Z1 b* @- s  h4 Z1 E$ e        {
! o8 V0 t( y2 T9 [% d, B+ w3 W: h            l_vaIndex.iVal = iIndex; // 设置循环索引
* l7 w* i+ G8 V0 m' ?
/ r! y; `& t0 E; H( g            // 取得字段名称
# x! P8 N' w  x: ?+ p3 ?            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
! T" z4 t3 I0 I  L' ^* q9 p( P( w) [* R# ]
            // 取得字段属性* u1 h  @2 z" o, b+ U+ s
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;# ^; @: o6 m3 ]) H' j
        }: j( h2 b( n8 i$ ?$ U2 [
        return S_OK;% K% W/ S( M% y. v
    }% P( O# B1 s* k8 T7 I
    catch( _com_error & a_pComError )
2 ^5 f6 O8 R- M& d- H; l' i9 @    {4 }+ ^% {1 _7 S, ]% @. h/ H" q
        …. // 错误处理
* n2 l- R' f8 w7 z: x        return E_UNEXPECTED;: ?2 m; f  Z, q, c1 Y
    }
) z( x: J; x5 W7 ~' N* `    catch(...)# z! r! D' ~& m5 I7 k' C1 y
    {
- ?( }* w/ M+ o$ N7 Q        …. // 错误处理
5 ~$ @  g$ \/ Z& y        return E_UNEXPECTED;* |8 A. C' L7 u( v' n( U
    }- h" T" L; ^& ?: g% p
}
  b, S6 U( U: ~8 z# \
& h" g2 q% y& Y8 q. W3 e. h5 n8 |
6.通过数据集(recordset)得到当前行记录8 N  z+ X7 z6 {5 a
9 {1 @$ n' `" H! _# E8 j5 Y
HRESULT getOneRecord( _RecordsetPtr ptrRs,
+ _1 a3 ~; x: ?, M( C                      const long lNoOfColumns," O& v; h5 d- s, R
                      _variant_t varValue[] )
* y; u* v0 f, a{
. R1 @3 a1 v% W" h% Q    try
5 Q+ a" A) A3 C    {5 x4 ?2 I' W4 d$ [
        // 参数变量! j( e1 p6 ?8 h' O) e6 V
        _variant_t l_vaIndex;
( `$ R9 I! `7 w, h        l_vaIndex.vt = VT_I2;0 r! M6 R' q" k# K1 G; Z
6 s% B. y( v4 B0 N) P5 X
        // 循环取得列的值9 {/ J* j8 [  k0 `: L& |: y! c( S
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )
! l# p( h6 M8 Y# @7 K' E% g7 i6 x        {
- I' s4 R* J- N3 o) y7 N            l_vaIndex.iVal = lIndex;
. Y6 U( A& H- s1 B3 ~3 A* {" B
1 Y1 i$ P6 _, y! I            // 取得字段值
8 @$ }" [0 v) w( ^' X8 o            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;; {; |2 u% _( |7 w5 k) X4 z
        }
4 I3 y5 v- l: B  k" U; X        return S_OK;
+ \& ^5 C# g4 H    }
& K/ v, O& f8 t    catch( _com_error & a_pComError )' o7 ?4 e  I3 D- h
    {) s( K/ ]" H8 _# ~* W5 h) j5 l7 i
        …. // 错误处理
& t1 c' D  i9 |' E( p        return E_UNEXPECTED;
2 z/ P) y. i4 r& e    }
6 ?8 J! O( O; p& o$ q    catch(...)% n- t8 K+ W, t' y6 \) A+ `
    {
: x8 r) o) {. j' O; x        …. // 错误处理+ n+ }1 F9 K6 P5 P/ s1 m9 C, ~* K
        return E_UNEXPECTED;
* t3 x9 S" j+ ?3 ]0 l    }1 e/ [' L! o$ T6 x4 s7 _( \
}
. `7 U! L4 @0 \& w
0 h9 x; T6 G4 u) Z1 o' y1 R0 J0 V( [9 e3 C' M! T) I: A1 m
7.出错情况下错误信息的取得9 R( A* d' }% v
" N( \& E2 k" l9 f0 Q( L+ T* p& a
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );7 r4 _1 Y' G8 x- z% H$ F
{
' C& a6 j) b5 }2 ~/ \% e    // COM 错误取得) D( `9 y7 P4 I3 z9 W2 q+ R
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常9 K) x! p% ^' M, y+ V7 }
    char lpComErrorStr512];5 @; ^; V. h5 {0 A  k' K0 W3 y1 W
* y" {5 W2 y! n5 A, O
    sprintf( lpComErrorStr512,
) @# p1 p$ `9 g0 X! M+ c( f' R, p             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",4 D8 d" z2 b' d9 Y4 h0 K7 r6 f6 j
             pComError.Error(),                  // 错误编号
; {  y7 c- ^' T4 g: x: L             pComError.ErrorMessage(),           // 错误信息# b1 ^+ f2 A; x+ x& A. m5 \! ^
             (LPCSTR) pComError.Source(),        // 错误源
) K. h* `9 W" w; i: r5 ]% `0 j4 ^4 d             (LPCSTR) pComError.Description() ); // 错误描述
! t$ C$ C3 z6 s  J* H+ K0 Y, B" Q# s; ^2 a; M* ~1 ?2 k+ E
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
6 u# L9 B5 C' i; u0 U    // ADO错误取得
! X7 |# b# I. H5 s- m8 J- s! N; A  S$ `/ H/ x0 o9 n, w
    ErrorPtr pErr = NULL;- _- q/ R  M% I* v3 J
    if( (ptrConn ->Errors->Count) > 0)! U- U2 K  E' d! w% o+ b
    {2 V% m/ b0 q3 D* H+ f; ?
        long nCount = ptrConn ->Errors->Count;! w6 Z1 M9 \- C) i; T
        for( long i = 0; i < nCount; i++ )
. u% o" \* L8 ^+ p+ e5 w; J        {9 N# @$ f% q# j+ M* \
            pErr = a_pConnPtr->Errors->GetItem(i);3 @; n' S2 H% V( B

& k6 \5 G' R1 a/ }  U% U, c            char l_pchErrorString[512];
  m# W' |: W! [* G, S. _* J8 C            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
% @& |0 C  x/ ?% D                     pErr->Number,         // 错误编号: c! V4 J5 I. d7 Q
                     pErr->Description );  // 错误描述+ j- r. k5 ]! {" Q3 O( p/ h1 l
        }# u# w! P  a1 K) H( M3 j* K
    }
5 f+ l7 v, d7 M- ]5 r) \* ?' f  a
7 e7 z) A2 ]; c1 T4 W+ b    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
" c& b& o0 m1 S    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 23:51 , Processed in 0.019646 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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