您好,欢迎访问一九零五行业门户网

VC++中使用ADO方式操作ACCESS数据库(转)

ado(activex data object)是microsoft数据库应用程序开发的新接口,是建立在ole db之上的高层数据库访问技术,即使你对ole db,com不了解也能轻松对付ado,因为它非常简单易用,甚至比你以往所接触的odbc api、dao、rdo都要容易使用,并不失灵活性。本文详细
ado(activex data object)是microsoft数据库应用程序开发的新接口,是建立在ole db之上的高层数据库访问技术,即使你对ole db,com不了解也能轻松对付ado,因为它非常简单易用,甚至比你以往所接触的odbc api、dao、rdo都要容易使用,并不失灵活性。本文详细地介绍在visual c++开发环境下如何使用ado来进行数据库应用程序开发,并给出示例代码。为了使读者朋友都能测试本例提供的代码,我们采用access数据库,您可以直接在我们提供的示例代码中找到这个test.mdb。程序编译运行后的效果如图一所示:
图一、ado操作acess数据库的界面效果图
一、实现方法
万事开头难,任何一种新技术对于初学者来说最重要的还是入门,掌握其要点。让我们来看看ado数据库开发的基本流程吧!它的基本步骤如下:
(1)初始化com库,引入ado库定义文件
(2)用connection对象连接数据库
(3)利用建立好的连接,通过connection、command对象执行sql命令,或利用recordset对象取得结果记录集进行查询、处理。
(4)使用完毕后关闭连接释放对象。
下面我们将详细介绍上述步骤并给出相关代码。
1、com库的初始化
我们可以使用afxoleinit()来初始化com库,这项工作通常在cwinapp::initinstance()的重载函数中完成,请看如下代码:
bool cadotest1app::initinstance()
{
 afxoleinit();
 ......
}
2、用#import指令引入ado类型库
为了引入ado类型库,需要在项目的stdafx.h文件中加入如下语句:
#import c:/program files/common files/system/ado/msado15.dll
no_namespace rename(eof,adoeof)
这一语句有何作用呢?其最终作用同我们已经十分熟悉的#include类似,编译的时候系统会为我们生成msado15.tlh,ado15.tli两个c++头文件来定义ado库。
需要读者朋友注意的是:您的开发环境中msado15.dll不一定在这个目录下,请按实际情况修改;在编译的时候可能会出现如下警告,对此微软在msdn中作了说明,并建议我们不要理会这个警告:msado15.tlh(405) : warning c4146: unary minus operator applied to unsigned type, result still unsigned。
3、创建connection对象并连接数据库
为了首先我们需要添加一个指向connection对象的指针_connectionptr m_pconnection,下面的代码演示了如何创建connection对象实例及如何连接数据库并进行异常捕捉:
bool cadotest1dlg::oninitdialog()
{
 cdialog::oninitdialog();
 hresult hr;
 try
 {
hr = m_pconnection.createinstance(adodb.connection);///创建connection对象
if(succeeded(hr))
{
 hr = m_pconnection->open(provider=microsoft.jet.oledb.4.0;
 data source=test.mdb,,,admodeunknown);///连接数据库
 //上面一句中连接字串中的provider是针对access2000环境的,对于access97,
 //需要改为:provider=microsoft.jet.oledb.3.51;
}
 }
 catch(_com_error e)///捕捉异常
 {
cstring errormessage;
errormessage.format(连接数据库失败!/r/n错误信息:%s,e.errormessage());
afxmessagebox(errormessage);///显示错误信息
 }
在这段代码中我们是通过connection对象的open方法来进行连接数据库的,下面是该方法的原型:
hresult connection15::open ( _bstr_t connectionstring, _bstr_t userid, _bstr_t password, long options );
上述函数中参数connectionstring为连接字串;参数userid是用户名;参数password是登陆密码;参数options是连接选项,用于指定connection对象对数据的更新许可权,一般情况下options可以是如下几个常量:
admodeunknown:缺省。当前的许可权未设置
admoderead:只读
admodewrite:只写
admodereadwrite:可以读写
admodesharedenyread:阻止其它connection对象以读权限打开连接
admodesharedenywrite:阻止其它connection对象以写权限打开连接
admodeshareexclusive:阻止其它connection对象以读写权限打开连接
admodesharedenynone:阻止其它connection对象以任何权限打开连接
我们给出一些常用的连接方式供大家参考:
(1)通过jet数据库引擎对access2000数据库的连接:
m_pconnection->open(provider=microsoft.jet.oledb.4.0;
data source=c://test.mdb,,,admodeunknown);
(2)通过dsn数据源对任何支持odbc的数据库进行连接:
m_pconnection->open(data source=adotest;uid=sa;pwd=;,,,admodeunknown);
(3)不通过dsn对sql server数据库进行连接:
m_pconnection->open(driver={sql server};server=127.0.0.1;database=vckbase;
uid=sa;pwd=139,,,admodeunknown);
其中server是sql服务器的名称,database是库的名称。
connection对象除open()方法外还有许多方法,我们先介绍connection对象中两个有用的属性connectiontimeout与state。connectiontimeout用来设置连接的超时时间,需要在open之前调用,例如:
m_pconnection->connectiontimeout = 5;///设置超时时间为5秒
m_pconnection->open(data source=adotest;,,,admodeunknown);
state属性指明当前connection对象的状态,0表示关闭,1表示已经打开,我们可以通过读取这个属性来作相应的处理,例如:
if(m_pconnection->state)
m_pconnection->close(); ///如果已经打开了连接则关闭它
4、执行sql命令并取得结果记录集
为了取得结果记录集,我们定义一个指向recordset对象的指针:_recordsetptr m_precordset;
并为其创建recordset对象的实例: m_precordset.createinstance(adodb.recordset),sql命令的执行可以采用多种形式,下面我们一一进行阐述。
(1)利用connection对象的execute方法执行sql命令
execute()方法的原型如下所示:
_recordsetptr connection15::execute ( _bstr_t commandtext, variant * recordsaffected, long options )
其中commandtext是命令字串,通常是sql命令。参数recordsaffected是操作完成后所影响的行数, 参数options表示commandtext中内容的类型,options可以取如下值之一:adcmdtext表明commandtext是文本命令;adcmdtable表明commandtext是一个表名;adcmdproc表明commandtext是一个存储过程;adcmdunknown表明commandtext内容未知。execute()函数执行完后返回一个指向记录集的指针,下面我们给出具体代码并作说明:
_variant_t recordsaffected;
///执行sql命令:create table创建表格users,users包含四个字段:整形id,字符串username,整形old,日期型birthday
m_pconnection->execute(create table users(id integer,username
text,old integer,birthday datetime),&recordsaffected,adcmdtext);
///往表格里面添加记录
m_pconnection->execute(insert into users(id,username,old,birthday)
values (1, 'washington',25,'1970/1/1'),&recordsaffected,adcmdtext);
///将所有记录old字段的值加一
m_pconnection->execute(update users set old = old+1,&recordsaffected,adcmdtext);
///执行sql统计命令得到包含记录条数的记录集
m_precordset = m_pconnection->execute(select count(*) from
users,&recordsaffected,adcmdtext);
_variant_t vindex = (long)0;
_variant_t vcount = m_precordset->getcollect(vindex);///取得第一个字段的值放入vcount变量
m_precordset->close();///关闭记录集
cstring message;
message.format(共有%d条记录,vcount.lval);
afxmessagebox(message);///显示当前记录条数
(2)利用command对象来执行sql命令
_commandptr m_pcommand;
m_pcommand.createinstance(adodb.command);
_variant_t vnull;
vnull.vt = vt_error;
vnull.scode = disp_e_paramnotfound;///定义为无参数
m_pcommand->activeconnection = m_pconnection;///非常关键的一句,将建立的连接赋值给它
m_pcommand->commandtext = select * from users;///命令字串
m_precordset = m_pcommand->execute(&vnull,&vnull,adcmdtext);
//执行命令取得记录集
在这段代码中我们只是用command对象来执行了select查询语句,command对象在进行存储过程的调用中能真正体现它的作用。下次我们将详细介绍。
(3)直接用recordset对象进行查询取得记录集,例如:
m_precordset->open(select * from users,_variant_t((idispatch *)m_pconnection,true),
adopenstatic,adlockoptimistic,adcmdtext);
open()方法的原型如下:
hresult recordset15::open ( const _variant_t & source, const _variant_t & activeconnection, enum cursortypeenum cursortype, enum locktypeenum locktype, long options )
上述函数中参数source是数据查询字符串;参数activeconnection是已经建立好的连接(我们需要用connection对象指针来构造一个_variant_t对象);参数cursortype光标类型,它可以是以下值之一;请看这个枚举结构:
enum cursortypeenum
{
 adopenunspecified = -1,///不作特别指定
 adopenforwardonly = 0,///前滚静态光标。这种光标只能向前浏览记录集,比如用movenext向前滚动,这种方式可以提高浏览速度。但诸如bookmark,recordcount,absoluteposition,absolutepage都不能使用
 adopenkeyset = 1,///采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的操作对你是可见的。
 adopendynamic = 2,///动态光标。所有数据库的操作都会立即在各用户记录集上反应出来。
 adopenstatic = 3///静态光标。它为你的记录集产生一个静态备份,但其它用户的新增、删除、更新操作对你的记录集来说是不可见的。
};
参数locktype表示数据库的锁定类型,它可以是以下值之一,请看如下枚举结构:
enum locktypeenum
{
 adlockunspecified = -1,///未指定
 adlockreadonly = 1,///只读记录集
 adlockpessimistic = 2,悲观锁定方式。数据在更新时锁定其它所有动作,这是最安全的锁定机制
 adlockoptimistic = 3,乐观锁定方式。只有在你调用update方法时才锁定记录。在此之前仍然可以做数据的更新、插入、删除等动作
 adlockbatchoptimistic = 4,乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。
};
参数options的含义请参考本文中对connection对象的execute()方法的介绍。
5、记录集的遍历、更新
根据我们刚才通过执行sql命令建立好的users表,它包含四个字段:id,username,old,birthday
以下的代码实现:打开记录集,遍历所有记录,删除第一条记录,添加三条记录,移动光标到第二条记录,更改其年龄数据,保存到数据库。
_variant_t vusername,vbirthday,vid,vold;
_recordsetptr m_precordset;
m_precordset.createinstance(adodb.recordset);
m_precordset->open(select * from users,_variant_t((idispatch*)m_pconnection,true),
adopenstatic,adlockoptimistic,adcmdtext);
while(!m_precordset->adoeof)
///这里为什么是adoeof而不是eof呢?还记得rename(eof,adoeof)这一句吗?
{
 vid = m_precordset->getcollect(_variant_t((long)0));///取得第1列的值,从0开始计数,你也可以直接给出列的名称;
 vusername = m_precordset->getcollect(username);///取得username字段的值
 vold = m_precordset->getcollect(old);
 vbirthday = m_precordset->getcollect(birthday);
 ///在debug方式下的output窗口输出记录集中的记录
 if(vid.vt != vt_null && vusername.vt != vt_null && vold.vt != vt_null &&
 vbirthday.vt != vt_null)
 trace(id:%d,姓名:%s,年龄:%d,生日:%s/r/n,vid.lval,(lpctstr)(_bstr_t)vusername,vold.lval,(lpctstr)(_bstr_t)vbirthday);
 m_precordset->movenext();///移到下一条记录
}
m_precordset->movefirst();///移到首条记录
m_precordset->delete(adaffectcurrent);///删除当前记录
///添加三条新记录并赋值
for(int i=0;i{
 m_precordset->addnew();///添加新记录
 m_precordset->putcollect(id,_variant_t((long)(i+10)));
 m_precordset->putcollect(username,_variant_t(叶利钦));
 m_precordset->putcollect(old,_variant_t((long)71));
 m_precordset->putcollect(birthday,_variant_t(1930-3-15));
}
m_precordset->move(1,_variant_t((long)adbookmarkfirst));///从第一条记录往下移动一条记录,即移动到第二条记录处
m_precordset->putcollect(_variant_t(old),_variant_t((long)45));///修改其年龄
m_precordset->update();///保存到库中
6、关闭记录集与连接
记录集或连接都可以用close()方法来关闭:
m_precordset->close();///关闭记录集
m_pconnection->close();///关闭连接
至此,我想读者朋友已经熟悉了ado操作数据库的大致流程,也许您已经胸有成竹,也许您还有点胡涂,不要紧!建议你尝试写几个例子,这样会更好地熟悉ado,最后我给大家写了一个小例子,例子实现的功能是读出所有记录并放到列表控件中,同时可以添加、删除、修改记录。
二、编程步骤
1、 启动visual c++6.0,生成一个基于对话框的应用程序,将该程序命名为adotest1;
2、 在对话框界面上放置显示记录列表控件和添加、删除记录用的的编辑、按钮控件,具体设置参加代码中的对话框资源部分;
3、 使用class wizard为添加、修改数据库记录的按钮添加消息响应函数;
4、 添加成程序代码,编译运行程序。
三、程序代码
/////////////////////////////////////////////////// adotest1dlg.h : header file
#if !defined(afx_adotest1dlg_h__29b385c0_02c0_4588_a8b4_d0efbb4f578d__included_)
#define afx_adotest1dlg_h__29b385c0_02c0_4588_a8b4_d0efbb4f578d__included_
#if _msc_ver >1000
#pragma once
#endif // _msc_ver >1000
class cadotest1dlg : public cdialog
{
 // construction
 public:
bool m_bautosave;
void savedata();
void loaddata();
_variant_t vuserid,vusername,vold,vbirthday;
bool m_bsuccess;
int m_ncurrentsel;
_recordsetptr m_precordset;
cadotest1dlg(cwnd* pparent = null); // standard constructor
// dialog data
//{{afx_data(cadotest1dlg)
 enum { idd = idd_adotest1_dialog };
 cbutton m_cdelitem;
 cbutton m_cadditem;
 clistctrl m_userlist;
 uint m_nuserid;
 uint m_nold;
 cstring m_susername;
 coledatetime m_tbirthday;
//}}afx_data
// classwizard generated virtual function overrides
//{{afx_virtual(cadotest1dlg)
 protected:
virtual void dodataexchange(cdataexchange* pdx); // ddx/ddv support
//}}afx_virtual
// implementation
 protected:
hicon m_hicon;
// generated message map functions
//{{afx_msg(cadotest1dlg)
 virtual bool oninitdialog();
 afx_msg void onsyscommand(uint nid, lparam lparam);
 afx_msg void onpaint();
 afx_msg hcursor onquerydragicon();
 virtual void onok();
 afx_msg void onadditem();
 afx_msg void ondelitem();
 afx_msg void onitemchangeduserlist(nmhdr* pnmhdr, lresult* presult);
//}}afx_msg
declare_message_map()
};
#endif
////////////////////////////////////////////////////// adotest1dlg.cpp : implementation file
#include stdafx.h
#include adotest1.h
#include adotest1dlg.h
#ifdef _debug
#define new debug_new
#undef this_file
static char this_file[] = __file__;
#endif
extern cadotest1app theapp;
class caboutdlg : public cdialog
{
 public:
caboutdlg();
// dialog data
//{{afx_data(caboutdlg)
 enum { idd = idd_aboutbox };
//}}afx_data
// classwizard generated virtual function overrides
//{{afx_virtual(caboutdlg)
 protected:
virtual void dodataexchange(cdataexchange* pdx); // ddx/ddv support
//}}afx_virtual
// implementation
 protected:
//{{afx_msg(caboutdlg)
//}}afx_msg
 declare_message_map()
};
caboutdlg::caboutdlg() : cdialog(caboutdlg::idd)
{
 //{{afx_data_init(caboutdlg)
 //}}afx_data_init
}
void caboutdlg::dodataexchange(cdataexchange* pdx)
{
 cdialog::dodataexchange(pdx);
 //{{afx_data_map(caboutdlg)
 //}}afx_data_map
}
begin_message_map(caboutdlg, cdialog)
 //{{afx_msg_map(caboutdlg)
// no message handlers
 //}}afx_msg_map
end_message_map()
cadotest1dlg::cadotest1dlg(cwnd* pparent /*=null*/)
: cdialog(cadotest1dlg::idd, pparent)
{
 //{{afx_data_init(cadotest1dlg)
m_nuserid = 0;
m_nold = 0;
m_susername = _t();
m_tbirthday = coledatetime::getcurrenttime();
 //}}afx_data_init
 // note that loadicon does not require a subsequent destroyicon in win32
 m_hicon = afxgetapp()->loadicon(idr_mainframe);
 m_ncurrentsel = -1;
 m_bsuccess = false;
 m_bautosave = true;
}
void cadotest1dlg::dodataexchange(cdataexchange* pdx)
{
 cdialog::dodataexchange(pdx);
 //{{afx_data_map(cadotest1dlg)
ddx_control(pdx, idc_delitem, m_cdelitem);
ddx_control(pdx, idc_additem, m_cadditem);
ddx_control(pdx, idc_userlist, m_userlist);
ddx_text(pdx, idc_userid, m_nuserid);
ddx_text(pdx, idc_old, m_nold);
ddx_text(pdx, idc_username, m_susername);
ddx_datetimectrl(pdx, idc_datetimepicker1, m_tbirthday);
 //}}afx_data_map
}
begin_message_map(cadotest1dlg, cdialog)
//{{afx_msg_map(cadotest1dlg)
 on_wm_syscommand()
 on_wm_paint()
 on_wm_querydragicon()
 on_bn_clicked(idc_additem, onadditem)
 on_bn_clicked(idc_delitem, ondelitem)
 on_notify(lvn_itemchanged, idc_userlist, onitemchangeduserlist)
//}}afx_msg_map
end_message_map()
bool cadotest1dlg::oninitdialog()
{
 cdialog::oninitdialog();
 m_cdelitem.enablewindow(false);
 ::sendmessage(m_userlist.m_hwnd, lvm_setextendedlistviewstyle,
 lvs_ex_fullrowselect, lvs_ex_fullrowselect);
 //////////为列表控件添加列//////////
 m_userlist.insertcolumn(0,用户id,lvcfmt_left,60);
 m_userlist.insertcolumn(1,用户名,lvcfmt_left,100);
 m_userlist.insertcolumn(2,年龄,lvcfmt_left,60);
 m_userlist.insertcolumn(3,生日,lvcfmt_left,100);
 //////////读取数据库中的信息添加到列表控件///////////
 int nitem;
 _variant_t vusername,vbirthday,vid,vold;
 try
 {
m_precordset.createinstance(adodb.recordset);
m_precordset->open(select*from users,
_variant_t((idispatch*)theapp.m_pconnection,true),
adopenstatic,adlockoptimistic,adcmdtext);
m_bsuccess = true;
while(!m_precordset->adoeof)
{
 vid = m_precordset->getcollect(id);
 vusername = m_precordset->getcollect(username);
 vold = m_precordset->getcollect(old);
 vbirthday = m_precordset->getcollect(birthday);
 nitem=m_userlist.insertitem(0xffff,(_bstr_t)vid);
 m_userlist.setitem(nitem,1,1,(_bstr_t)vusername,null,0,0,0);
 m_userlist.setitem(nitem,2,1,(_bstr_t)vold,null,0,0,0);
 m_userlist.setitem(nitem,3,1,(_bstr_t)vbirthday,null,0,0,0);
 m_precordset->movenext();
}
 }
 catch(_com_error e)///捕捉异常
 {
afxmessagebox(读取数据库失败!);///显示错误信息
 }
 assert((idm_aboutbox & 0xfff0) == idm_aboutbox);
 assert(idm_aboutbox  cmenu* psysmenu = getsystemmenu(false);
 if (psysmenu != null)
 {
cstring straboutmenu;
straboutmenu.loadstring(ids_aboutbox);
if (!straboutmenu.isempty())
{
 psysmenu->appendmenu(mf_separator);
 psysmenu->appendmenu(mf_string, idm_aboutbox, straboutmenu);
}
 }
 seticon(m_hicon, true); // set big icon
 seticon(m_hicon, false); // set small icon
 return true; // return true unless you set the focus to a control
}
void cadotest1dlg::onsyscommand(uint nid, lparam lparam)
{
 if ((nid & 0xfff0) == idm_aboutbox)
 {
caboutdlg dlgabout;
dlgabout.domodal();
 }
 else
 {
cdialog::onsyscommand(nid, lparam);
 }
}
void cadotest1dlg::onpaint()
{
 if (isiconic())
 {
cpaintdc dc(this); // device context for painting
sendmessage(wm_iconerasebkgnd, (wparam) dc.getsafehdc(), 0);
// center icon in client rectangle
int cxicon = getsystemmetrics(sm_cxicon);
int cyicon = getsystemmetrics(sm_cyicon);
crect rect;
getclientrect(&rect);
int x = (rect.width() - cxicon + 1) / 2;
int y = (rect.height() - cyicon + 1) / 2;
// draw the icon
dc.drawicon(x, y, m_hicon);
 }
 else
 {
cdialog::onpaint();
 }
}
hcursor cadotest1dlg::onquerydragicon()
{
 return (hcursor) m_hicon;
}
void cadotest1dlg::onok()
{
 if(m_bsuccess)
 {
m_precordset->update();
m_precordset->close();
 }
 cdialog::onok();
}
void cadotest1dlg::onadditem()
{
 if(updatedata())
if(m_susername.getlength()>0)
{
 m_precordset->addnew();
 m_ncurrentsel = m_userlist.insertitem(0xffff,);
 savedata();///保存数据
 m_userlist.setitemstate(m_ncurrentsel,lvis_selected|lvis_focused,lvis_selected|lvis_focused);
 m_userlist.sethotitem(m_ncurrentsel);
 m_userlist.setfocus();
}
else
 afxmessagebox(请输入用户名);
}
void cadotest1dlg::ondelitem()
{
 m_bautosave = false;
 if(m_ncurrentsel >= 0)
 {
m_userlist.deleteitem(m_ncurrentsel);
int count = m_userlist.getitemcount();
if(count  m_ncurrentsel = count-1;
 m_precordset->delete(adaffectcurrent);
 m_precordset->movenext();
 loaddata();
 m_userlist.setitemstate(m_ncurrentsel,lvis_selected|lvis_focused,lvis_selected|lvis_focused);
 m_userlist.setfocus();
 }
 m_bautosave = true;
}
//////////在选择列表框的时候调用///////////////////
void cadotest1dlg::onitemchangeduserlist(nmhdr* pnmhdr, lresult* presult)
{
 nm_listview* pnmlistview = (nm_listview*)pnmhdr;
 if(pnmlistview->unewstate&lvis_selected)
 {
updatedata();
savedata();///保存旧数据
m_ncurrentsel = pnmlistview->iitem;
loaddata();///加载新数据
m_cdelitem.enablewindow();
 }
 *presult = 0;
}
//////将记录集中的数据加载到编辑框/////
void cadotest1dlg::loaddata()
{
 m_precordset->move(m_ncurrentsel,_variant_t((long)adbookmarkfirst));
 vuserid = m_precordset->getcollect(id);
 vusername = m_precordset->getcollect(username);
 vold = m_precordset->getcollect(old);
 vbirthday = m_precordset->getcollect(birthday);
 m_nuserid = vuserid.lval;
 m_susername = (lpctstr)(_bstr_t)vusername;
 m_nold = vold.lval;
 m_tbirthday = vbirthday;
 updatedata(false);
}
/////将编辑框的数据保存到记录集与列表框
void cadotest1dlg::savedata()
{
 if(!m_precordset->adoeof && m_ncurrentsel >= 0 && m_bautosave)
 {
vuserid = (long)m_nuserid;
vusername = m_susername;
vold = (long)m_nold;
vbirthday = m_tbirthday;
m_precordset->putcollect(id,vuserid);
m_precordset->putcollect(username,vusername);
m_precordset->putcollect(old,vold);
m_precordset->putcollect(birthday,vbirthday);
m_userlist.setitem(m_ncurrentsel,0,lvif_text,(_bstr_t)vuserid,null,0,0,0);
m_userlist.setitem(m_ncurrentsel,1,lvif_text,(_bstr_t)vusername,null,0,0,0);
m_userlist.setitem(m_ncurrentsel,2,lvif_text,(_bstr_t)vold,null,0,0,0);
m_userlist.setitem(m_ncurrentsel,3,lvif_text,(_bstr_t)vbirthday,null,0,0,0);
 }
}
////////////////////////////////////////////////////////////////////////
bool cadotest1app::initinstance()
{
 afxenablecontrolcontainer();
 afxoleinit();///初始化com库
 hresult hr; ////////////连接数据库//////////////
 try
 {
hr = m_pconnection.createinstance(adodb.connection);///创建connection对象
if(succeeded(hr))
{
 hr = m_pconnection->open(provider=microsoft.jet.oledb.4.0;
 data source=test.mdb,,,admodeunknown);///连接数据库
 ///上面一句中连接字串中的provider是针对access2000环境的,
 /////对于access97,需要改为:provider=microsoft.jet.oledb.3.51; }
}
 }
 catch(_com_error e)///捕捉异常
 {
cstring errormessage;
errormessage.format(连接数据库失败!/r/n错误信息:%s,e.errormessage());
afxmessagebox(errormessage);///显示错误信息
return false;
 }
 #ifdef _afxdll
enable3dcontrols(); // call this when using mfc in a shared dll
 #else
enable3dcontrolsstatic(); // call this when linking to mfc statically
 #endif
 cadotest1dlg dlg;
 m_pmainwnd = &dlg;
 int nresponse = dlg.domodal();
 if (nresponse == idok)
 {}
 else if (nresponse == idcancel)
 {}
 return false;
}
/////////////////////////////////////////////
int cadotest1app::exitinstance()
{
 if(m_pconnection->state)
 m_pconnection->close(); ///如果已经打开了连接则关闭它
 return cwinapp::exitinstance();
}
四、小结
限于篇幅ado中的许多内容还没有介绍,如绑定方式处理记录集数据、存储过程的调用、事务处理、图象在数据库中的保存与读取、与表格控件的配合使用等。如果读者对上述内容感性认识的话,可以自行参考相关编程资料。
其它类似信息

推荐信息