MFC连接数据库的三种方法:
ODBC(开放式数据互联),OLEDB,DAO,关于这三种之间的关系从下图中可直观理解出来:
图1.1 OLEDB与ADO
ODBC提供了一组标准的、基于SQL的API接口,使得任何数据库都可以通过ODBC驱动器与指定的DBMS相连,并让应用程序可以通过ODBC驱动管理器中响应的驱动程序来访问数据库。
在visual C++中,MFC提供了操作ODBC数据库的相关类:
CDatebase――表示应用程序和需要访问的数据源之间的连接,通过该对象可以操作数据源。
CRecordSet――表示从数据源中提取出的表的记录集,并提供了对记录进行操作的的许多功能。如:查询、添加、修改、删除等。
CRecordView t――控制并显示数据库记录,该视图是直接连接到一个CRecordSet对象的表单视图。
MFC中提供了AppWizard能够自动将创建的应用程序框架通过ODBC连接到数据库。首先需要在本机中配置ODBC数据源。
虽然利用AppWizard能简单的实现数据库的互联,并且自动提供一个继承自CRecordSet的类,如图:
图1.2 自动生成的Recordset类
从而接下来的操作,都可以利用这个set类对象,而这个类中,已经当在向导中选择数据源,自动映射了相应的数据表中的字段。接下来需要做的只是把界面中的控件与这些对应变量绑定,就可以实现数据的显示。
而在view类中发现对于RecordSet对象,是通过doc类得来,如图:
图1.3 m_pSet的赋值
这不得不让人认为CRecord类是通过doc进行管理维护的,但追踪到doc类中,却什么也没有发现。关于这些vc自动维护暂时还清楚。
(动态集)dynaset与(快照)snapshots的区别:
动态集是被访问的数据库数据的动态视图;
记录集中所包含的记录成员在记录创建时确定;
能反映其他用户对记录集的修改;
能反映其他用户对记录集的删除(跳过被删除的记录)而其他用户对数据源记录的添加在调用CRecord::Requery之前是不能反映的。
快照是被访问的数据库数据的静态视图;
记录集中所包含的记录成员在记录集创建时确定;
不能反映其他用户对记录集的修改;
不能其他用户对记录集的添加和删除;
能正确地反映自身对记录的修改和删除,而记录的添加在调用CRecord::Requery之前是不可见的。
接下来观察自动生成类的的属性是怎么样与数据库中表的字段进行关联的,主要就是通过下面这个方法:
图1.4属性与数据库表字段绑定
这样,就可以通过操作类的字段来直接与数据库交互。后续的增删改查,皆是如此。
图1.5属性初始化
至此有理由相信:
CDatabase不为NULL,指向一个CDatabase类对象,且该对象已经通过调用CDatabase::Open成员函数与一个指定的数据源连接,则记录集类对象就直接建立在该数据源类对象上。以便通过该对象调用CRecordSet::Open成员函数打开记录集。
CDatabase::Open成员函数与缺省指定的数据源连接,最后完成一个记录集打开操作。
在后两种情况下,都需要在建立记录集时,调用成员函数CRecordSet::GetDefaultConnect获取指定的连接描述字,以便建立与指定的数据源连接。
OLEDB与ADO
OLEDB标准的具体体现是一组c++的API函数,就像ODBC标准中的ODBC API的一样,不同的是,OLEDB的API是符合COM标准、基于对象的。使用OLEDB API可以编写能够访问符合OLE DB标准的任何数据源的应用程序,也可以编写针对某种特定数据存储的查询处理程序和游标引擎,因此OLEDB标准实际上是规定了数据使用者和提供者之间的一种应用层协议。
为了使流行的各种编程语言都可以符合OLEDB标准的应用程序,微软在OLEDB API之上提供了一种面向对象、与语言无关的应用编程接口,这就是ADO。
Connection对象
Error对象
Command对象
Parameter对象
Recordset对象
Field对象
在ADO动态链接中包含了_ConnectionPtr,_CommandPtr,_RecordsetPtr,_ParameterPtr,_FieldPtr等接口。
VARIANT和_varinat_t――传输不同数据类型的数据
BSTR和_bstr_t――代替char*类型
引入ADB DLL
#import "C:\Program Files\Common Files\System\ado\msado15.dll"\
rename("EOF","_EOF")
using namespace ADODB;
首先我们需要说明一下用MFC OLE ClassWizard创建ADO应用的几个不可缺少的步骤:
从Tools菜单中,选择Options,然后选择Directories tab,在Show Directories中,选择Library Files,然后在directories增加路径C:\program files\common files\system\ado,这样做的目的是设置包含ADO类型库的路径。
从View菜单中,选择ClassWizard,点击Add Class按纽并选择From A Type Library...,然后在Type Library dialog box对话框中,从C:\program files\common files\system\ado选择文件msado15.dll,在Confirm Classes对话框中,选择所有列出的类并按OK按纽,退出ClassWizard。实际上,ClassWizard为你生成了两个文件msado15.h和msado15.cpp.
图1.6数据库连接
图1.7各数据库连接串
使用_ConnectionPtr接口执行查询的一般步骤是:
首先调用 CreateInstance为接口创建一个实例(或直接通过构造函数从堆栈中创建该实例),然后将连接字符串传递给Open函数交调用该函数打开数据库连接,成功建立数据库连接后,调用Execute函数执行一条SQL语句,或者调用BeginTrans函数开始一个事务;在完成所有数据库操作后,调用Close函数关闭数据库连接,如果执行的是一个事务,则在关闭数据库连接前调用CommitTrans提交事务。
图1.8 _ConnectionPtr操作数据库
图1.9 _ConnectionPtr操作数据库结果
#include "stdafx.h"
int main(int argc, char* argv[])
{
::CoInitialize(NULL);//must type this line
_ConnectionPtr con;
try{
con.CreateInstance("ADODB.Connection");//create connection instance
//set connection string
_bstr_t conStr="Provider=SQLOLEDB;Data Source=(local);Initial Catalog=MBOOK;\
Integrated Security=SSPI;User Name=sa;Password=123456";
con->Open(conStr,"","",adConnectUnspecified); //open the connection
con->BeginTrans();
// _bstr_t strSql="insert into TBOOK(ISBN,BName) values('7-121-03246-5','c++')";
// _bstr_t strSql="delete from TBOOK where ISBN='7-121-03246-5'";
// _bstr_t strSql="update TBOOK set BName='ASP',Author='sunquan' where ISBN='7-121-03246-5'";
// _bstr_t strSql="select * from TBOOK where ISBN='7-121-03246-5'";
con->Execute(strSql,NULL,adCmdText);
con->CommitTrans();
con->Close();
}catch(_com_error& e)
{
con->RollbackTrans();
printf(e.Description());
// AfxMessageBox(e.Description());
}
return 0;
}
图2.0 _RecordsetPtr操作数据库
图2.1 _RecordsetPtr操作数据库结果
图2.2 _RecordsetPtr添加数据
图2.3 _RecordsetPtr添加数据结果
图2.4 _RecordsetPtr查询数据
图2.5 _RecordsetPtr查询数据结果
图2.6 _RecordsetPtr删除数据
_CommandPtr接口通常可用来执行SQL命令以实现数据表记录的查询、添加、更新和删除等操作。
在使用_CommandPtr接口时,首先需要使用_ConnectionPtr接口建立一个数据库连接,并设置_CommandPtr接口中的ActiveConnection数据成员,然后指定执行命令的类型及命令语句,最后调用Execute函数执行指定的SQL命令。
图2.7 _CommandPtr操作存储过程
图2.8 创始存储过程
附:
_CommandPtr使用运行sql语句:
::CoInitialize(NULL);
_ConnectionPtr pConnection("ADODB.Connection");
_bstr_t conStr="Provider=SQLOLEDB;Data Source=(local);Initial Catalog=MBOOK;\
Integrated Security=SSPI;User Name=sa;Password=123456";
pConnection->Open(conStr,"","",adConnectUnspecified);
_CommandPtr pCmd("ADODB.Command");
pCmd->ActiveConnection=pConnection;
pCmd->CommandType=adCmdText;
pCmd->CommandText="insert into TBOOK(ISBN,BName) values('7-121-03246-3','c++')";
pCmd->Execute(NULL,NULL,adCmdText);
pConnection->Close();
_CommandPtr使用运行存储过程(1):
create PROC BOOK_DELETE
@ISBN char(18)
as
delete from TBOOK where ISBN=@ISBN
::CoInitialize(NULL);
_ConnectionPtr pConnection("ADODB.Connection");
_bstr_t conStr="Provider=SQLOLEDB;Data Source=(local);Initial Catalog=MBOOK;\
Integrated Security=SSPI;User Name=sa;Password=123456";
pConnection->Open(conStr,"","",adConnectUnspecified);
_CommandPtr pCmd("ADODB.Command");
pCmd->ActiveConnection=pConnection;
pCmd->CommandType=adCmdStoredProc;
pCmd->CommandText="BOOK_DELETE";
_ParameterPtr para;
para=pCmd->CreateParameter("ISBN",adChar,adParamInput,18);
para->Value="7-121-03246-8";
pCmd->Parameters->Append(para);
pCmd->Execute(NULL,NULL,adCmdStoredProc);
pCmd->Parameters->Delete(_variant_t((long)0));
pConnection->Close();
_CommandPtr使用运行存储过程(1):
create PROC BOOK_SUM
@BName char(8),
@total int output
AS
select @total=count(*) from TBOOK where BName=@BName
::CoInitialize(NULL);
_ConnectionPtr pConnection("ADODB.Connection");
_bstr_t conStr="Provider=SQLOLEDB;Data Source=(local);Initial Catalog=MBOOK;\
Integrated Security=SSPI;User Name=sa;Password=123456";
pConnection->Open(conStr,"","",adConnectUnspecified);
_CommandPtr pCmd("ADODB.Command");
pCmd->ActiveConnection=pConnection;
pCmd->CommandType=adCmdStoredProc;
pCmd->CommandText="BOOK_SUM";
_ParameterPtr paraName,paraCount;
paraName=pCmd->CreateParameter("BName",adChar,adParamInput,18);
paraName->Value="sunquan";
pCmd->Parameters->Append(paraName);
paraCount=pCmd->CreateParameter("COUNT",adInteger,adParamOutput,2);
pCmd->Parameters->Append(paraCount);
pCmd->Execute(NULL,NULL,adCmdStoredProc);
printf((_bstr_t)paraCount->GetValue());
pCmd->Parameters->Delete(_variant_t((long)0));
pConnection->Close();