VC与ADO数据库操作
VC与ADO数据库操作
学研部的同志们,大家好! 想开一次学习会,实习时间冲突了,只好把文档发给大家看了。重点推荐李振龙的BMP读图教程! 尤其是大三GIS班的同志,注意了,可能实习用得上的!
一、ADO简介
ADO(ActiveX Data Object)是Microsoft数据库应用程序开发的新接口,是建立在OLE DB之上的高层数据库访问技术,请不必为此担心,即使你对OLE DB,COM不了解也能轻松对付ADO,因为它非常简单易用,甚至比你以往所接触的ODBC API、DAO都要容易使用,
【1】为工程做准备
建一个基于对话框的工程,名字叫PlaceName。
加入一个ListControl控件,ID改成IDC_RESULT,顺便点一下Styles选项卡,把View改成Report,你可以看到对话框里的ListControl控件的样子已经变成带字段名的报表格式了。右击它,用ClassWizard添加成员变量,名字为m_LisCtrlResult。
按照上面的程序界面,加入一个编辑框(输入SQL语句用的),同上面添加m_LisCtrlResult成员变量一样,加入一个CString变量,名字为m_SqlText,还有一个“查询”按钮,把它叫为Query,双击它一下,VC会自动为它加入消息和函数的,名字也叫OnQuery(),等一下我们就用着那个函数的。
看到我们SpaceSoft的标志不?把你的照片换成BMP格式的,放上去吧!
定义一下要用着的变量:
class CPlaceNameDlg : public CDialog
{
// Construction
public:
_RecordsetPtr m_pRecordset; //定义一个RecordsetPtr对象,用来储存读出来的表
HRESULT hr; //查出后的表
Fields* fields; //储存查出后的字段
BSTR bstrColName; //储存一下字段名
long nRstCol; //SQL语句一共查出了几个字段?nRstCol个!
CString strColName[100]; //把查出的字段名转换成常见常用的CString类型,放在这个数组里边
……
}
//储存从数据库读出的数据,variant 变量能够存储所有系统定义类型的数据。
【2】COM库的初始化
我们可以使用AfxOleInit()来初始化COM库,这项工作通常在CWinApp::InitInstance()的重载函数中完成,请看如下代码:
BOOL CPlaceNameApp::InitInstance()
{
AfxOleInit();
......
}
【3】用#import指令引入ADO类型库
我们在stdafx.h中加入如下语句:(stdafx.h这个文件哪里可以找到?你可以在FileView中的Header Files里找到)
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
这一语句有何作用呢?其最终作用同我们熟悉的#include类似,编译的时候系统会为我们生成msado15.tlh,ado15.tli两个C++头文件来定义ADO库。
几点说明:
(1) 您的环境中msado15.dll不一定在这个目录下,请按实际情况修改
(2) 在编译的时候肯能会出现如下警告,对此微软在MSDN中作了说明,并建议我们不要理会这个警告。
msado15.tlh(405) : warning C4146: unary minus operator applied to unsigned type, result still unsigned
【4】创建Connection对象并连接数据库
首先我们需要添加一个指向Connection对象的指针,就是在PlaceName.h里加入下面一句,定义它:
_ConnectionPtr m_pConnection; //前面带“_”的语句一般是VC本来没有的东西,是外来的
下面的代码演示了如何创建Connection对象实例及如何连接数据库并进行异常捕捉。
BOOL CPlaceNameApp::InitInstance()
{
AfxEnableControlContainer();
AfxOleInit(); //使用OLE对象时,须加这一句
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 = placename.mdb",
"",
"",
adModeUnknown); //连接数据库
}
}
catch(_com_error e) //捕捉异常
{
CString errormessage;
errormessage.Format("Fail to connect the database! \r\n ErroeMessage:%s", e.ErrorMessage);
AfxMessageBox(errormessage); //show the error message
return FALSE;
}
……
}
在这段代码中我们是通过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:允许其它程序或对象以任何权限建立连接
对ACCESS2000数据库的连接(还有其他的连接方式,深入了解的话参看材料吧)
【4】执行SQL命令并取得结果记录集
为了取得结果记录集,我们在PlaceNameDlg.h里定义一个指向Recordset对象的指针,(刚才已经定义过了)
下面为其创建Recordset对象的实例: m_pRecordset.CreateInstance("ADODB.Recordset");
BOOL CPlaceNameDlg::OnInitDialog()
{
CDialog::OnInitDialog();
long i;
int nItem; //暂时储存ListControl的行号
try
{
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open((_bstr_t)m_SqlText,
_variant_t((IDispatch*)theApp.m_pConnection, true),
adOpenStatic,
adLockOptimistic,
adCmdText); //IDispatch 是关于OLE的东西,在此省略一点。我没查
///////////////////////////////////////////
hr = m_pRecordset->get_Fields (&fields); //得到记录集的字段集和
//为了放下查出的数据,把ListControl原来的数据清除了先!
//删除所有记录行
m_LisCtrlResult.DeleteAllItems();
//删除所有列表头
while(m_LisCtrlResult.DeleteColumn(0));
//更新窗口
this->UpdateWindow();
if(SUCCEEDED(hr))
fields->get_Count(&nRstCol); //得到记录集的字段集合中的字段的总个数
for(i = 0; i < nRstCol; i++)
{
fields->Item[i]->get_Name(&bstrColName); //得到记录集中的字段名
strColName[i] = bstrColName;
//////////为列表控件添加字段的名字//////////
m_LisCtrlResult.InsertColumn(i, strColName[i], LVCFMT_LEFT, 70);
}
////////////////////////////////////////////////
while(!m_pRecordset->adoEOF)
{
nItem = m_LisCtrlResult.InsertItem(0, NULL); //插入新的一行。把行号放在//了nItem里边。
for(i = 0; i < nRstCol; i++)
{
m_LisCtrlResult.SetItem(nItem, i, 1, (_bstr_t)m_pRecordset->GetCollect((_bstr_t)strColName[i]),
NULL, 0, 0, 0); //把读出来的数据项放入ListControl里边
}
m_pRecordset->MoveNext(); //记得使记录指针移动哦
}
}
catch(_com_error e)///捕捉异常
{
AfxMessageBox("Fail to read the database!");///显示错误信息
}
【4】使用SQL语句进行查询
很简单,在OnQuery函数里加入两句代码就好了!
void CPlaceNameDlg::OnQuery()
{
// TODO: Add your control notification handler code here
UpdateData();
this->SendMessage(WM_INITDIALOG);
}
【6】关闭记录集与连接
打开了记录集或连接,最好都关闭吧,用Close方法就可以。
m_pRecordset->Close();///关闭记录集
m_pConnection->Close();///关闭连接
在我们的例程里,是在ExitInstance()函数里关掉的。怎么加呢,看看下图!
下面是要加入的代码:
int CPlaceNameApp::ExitInstance()
{
// TODO: Add your specialized code here and/or call the base class
if(m_pConnection->State)
m_pConnection->Close(); ///如果已经打开了连接则关闭它
return CWinApp::ExitInstance();
}
至此,我已经介绍完了ADO操作数据库的大致流程,同是初学ADO,这个教程中的例程已经和刚开始做的都不一样了,也没有测试,我再改的。最好把代码自己敲一遍啊,这样可以你敲出“.”“->”VC就会提醒你有什么东西能用的。文档里没说明白的就看原代码吧,不要钱的!
希望继续关注SpaceSoft!
注意Connection对象的Open方法中的连接字符串参数必须是BSTR或_bstr_t类型。另外,本例是直接通过OLE DB Provider建立连接,所以无需建立数据源。
From MSDN
上面的代码是直接用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,乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。
};
/*
VIRIANT是ACTIVEX AUTOMATION需要用到的一种变量类型,
可以称之为通用数据类型,其实它是一个结构。
Variant 变量能够存储所有系统定义类型的数据。
如果把它们赋予 Variant 变量,则不必在这些数据的类型间进行转换;
VC 会自动完成任何必要的转换.
程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。
_variant_t //Constructs a _variant_t object. (From MSDN)
*/
_bstr_t
Microsoft Specific
A _bstr_t object encapsulates the BSTR data type. The class manages resource allocation and deallocation, via function calls to SysAllocString and SysFreeString, and other BSTR APIs when appropriate. The _bstr_t class uses reference counting to avoid excessive overhead.
BSTR是一个带长度前缀的字符串,主要由操作系统来管理的,所以要用api.主要用来和VB打交道的(VB里的string就是指它)
要操作它的API函数有很多,具体可以去查一下msdn.比如SysAllocString,SysFreeString等等.
vc里封装它的类如_bstr_t,及ATL中的CComBSTR等.
一个 BSTR 由头部和字符串组成,头部包含了字符串的长度信息,字符串中可以包含嵌入的 null 值。BSTR 是以指针的形式进行传递的。
(指针是一个变量,包含另外一个变量的内存地址,而不是数据。) BSTR 是 Unicode 的,即每个字符需要两个字节。
BSTR 通常以两字节的 null 字符结束。
wstr是宽字符,以双字节表示一个字符
bstr是为了与原先的basic字符兼容,它的最前面的4个字节为其长度,以'\0'结束
char 1 signed char –128 to 127 The keyword char identifies a data item that has 8 bits.
嘿嘿,够全吧
Visual C++开发数据库技术
Visual C++提供了多种访问数据库的技术,如下所示:
ODBC(Open DataBase Connectivity)
MFC ODBC(Microsoft Foundation Classes ODBC)
DAO (Data Access Object)
OLE DB(Object Link and Embedding DataBase)
ADO(ActiveX Data Object)
这些技术各有自己的特点,总结如下:
ODBC
ODBC是客户应用程序访问关系数据库时提供的一个统一的接口,对于不同的数据库,ODBC提供了一套统一的API,使应用程序可以应用所提供的API来访问任何提供了ODBC驱动程序的数据库。而且,ODBC已经成为一种标准,所以,目前所有的关系数据库都提供了ODBC驱动程序,这使ODBC的应用非常广泛,基本上可用于所有的关系数据库。
但由于ODBC只能用于关系数据库,使得利用ODBC很难访问对象数据库及其它非关系数据库。
由于ODBC是一种底层的访问技术,因些,ODBC API可以使客户应用程序能够从底层设置和控制数据库,完成一些高层数据库技术无法完成的功能。
MFC ODBC
由于直接使用ODBC API编写应用程序要编制大量代码,在Visual C++中提供了MFC ODBC类,封装了ODBC API,这使得利用MFC来创建ODBC的应用程序非常简便。
DAO
DAO提供了一种通过程序代码创建和操纵数据库的机制。多个DAO构成一个体系结构,在这个结构中,各个DAO对象协同工作。MFC DAO是微软提供的用于访问Microsoft Jet数据库文件(*.mdb)的强有力的数据库开发工具,它通过DAO的封装,向程序员提供了DAO丰富的操作数据库手段。
OLE DB
OLE DB是Visual C++开发数据库应用中提供的新技术,它基于COM接口。因此,OLE DB对所有的文件系统包括关系数据库和非关系数据库都提供了统一的接口。这些特性使得OLE DB技术比传统的数据库访问技术更加优越。
与ODBC技术相似,OLE DB属于数据库访问技术中的底层接口。
直接使用OLE DB来设计数据库应用程序需要大量的代码。在VC中提供了ATL模板,用于设计OLE DB数据应用程序和数据提供程序。
ADO
ADO技术是基于OLE DB的访问接口,它继承了OLE DB技术的优点,并且,ADO对OLE DB的接口作了封装,定义了ADO对象,使程序开发得到简化,ADO技术属于数据库访问的高层接口。
VC与ADO数据库操作的更多相关文章
- MFC ADO数据库操作
MFC ADO数据库操作 - 延陵小明 - CSDN博客 http://blog.csdn.net/guoming0000/article/details/7280070/ 内容比较乱,作为草稿,对现 ...
- vc调用mysql数据库操作例子
这里归纳了C API可使用的函数 函数 描述 mysql_affected_rows() 返回上次UPDATE.DELETE或INSERT查询更改/删除/插入的行数. mysql_autocommit ...
- ADO数据库操作
void CSjtestDlg::OnBnClickedButtonAdd() { // TODO: 在此添加控件通知处理程序代码 this->ShowWindow(SW_HIDE); DigA ...
- VC++中使用ADO方式操作ACCESS数据库
ADO(ActiveX Data Object)是Microsoft数据库应用程序开发的新接口,是建立在OLE DB之上的高层数据库访问技术,即使你对OLE DB,COM不了解也能轻松对付ADO,因为 ...
- Win10 64位系统ADO方式操作数据库失败解决方法
VC操作Access数据库一般通过ODBC.ADO.DAO等方式,但在我的Win10 64位操作系统中,通过ADO方式操作数据库会失败,无法读取数据.解决方法:1.首先确保Win10操作系统ado目录 ...
- ADO.NET操作数据库(一)
---恢复内容开始--- [1]ADO.Net简介2015-12-07-20:16:05 ADO.Net提供对Microsoft SQL Server数据源以及通过OLE DB和XML公开的数据源的一 ...
- 数据库操作(ADO)
QTP工具本身自带有数据查询和验证功能,但是使用的人会感觉这个功能使用起来比较麻烦,灵活性和复用性较低,于是我们选择了用脚本调用ADO组件实现数据库的操作,现总结下工作中用到的数据库操作,代码如下: ...
- MFC,ADO方式实现数据库操作
参考: MSDN数据访问编程 (MFC/ATL): https://msdn.microsoft.com/zh-cn/library/kd4ck1tt.aspx?f=255&MSPPError ...
- ado.net的简单数据库操作(二)之封装SqlHelperl类
今天我书接上回,接着昨天的ado.net的数据库操作的相关知识来讲哈! 从上篇文章给出的实例来看,你一定会发现,操作数据库其实还挺麻烦的,就连一个最简单的数据库操作语句都要包括 定义数据库连接字符串. ...
随机推荐
- python [1:3]
Python下标是以0开始的x[1:3]表示返回集合中下标1至3(不包括3)的元素集合x[:3] 表示返回从开始到下标3(不包括3)的元素集合x[3:]表示返回从下标3到结束的元素集合X[:]表示返回 ...
- 小菜鸟安装CocoaPods
刚来到公司,以前没有用过CocoaPods. 参考的以下两篇文章,都是转载的. 第一篇比较偏技术性,叫做<Mac下CocoaPods安装步骤> http://blog.csdn.net/a ...
- boost.spirit之解析C++头文件
环境:win7_64旗舰版,VS2008 场景:C++与lua交互是比较繁琐的,当我们编写一个C++类后,如果要给lua使用,就必须写一个lua包装类,将lua与原始C++类关联起来.其实这部分代码编 ...
- 多线程synchronized用例解析
当用synchronized来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.即使在执行过程中,CPU切换到别的线程了,因为有锁的缘故,其他线程也不会进来执行代码,而 ...
- 滚动条加粗和panel,gridControl结合用
private void FrmLotterycs_Load(object sender, EventArgs e) { t = 0; UserJuanquanTB = O.get_UserJuanq ...
- html5 --基础笔记2
1.autocomplete 可以给表单本身(不是fieldset)设置属性来禁用整个表单的自动完成功能 <form id="" method="" au ...
- Codeforces 691D Swaps in Permutation
Time Limit:5000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit Status Prac ...
- Windows线程同步(上)
先介绍一个创建线程的API,参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx ...
- 【Machine Learning in Action --2】K-近邻算法构造手写识别系统
为了简单起见,这里构造的系统只能识别数字0到9,需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32像素的黑白图像.尽管采用文本格式存储图像不能有效地利用内存空间,但是为了方便理 ...
- PAC全自动脚本代理
Proxy 极低成本绕过GFW的一个PAC代理 Download proxy.zip Proxy 轻量级的FQ工具,不需要安装客户端.可以设置系统代理,也可以设置浏览器代理或者配合SS等插件使用. 免 ...