由于最近项目上要使用ADO访问数据库,而网上又没有非常完整的帖子,干脆摸着石头过河来总结一个ADO的使用;首先不得不说ADO的使用率并不是很高
1.ADO是微软提供的访问各种数据库的统一接口,是对底层的COM技术OLE DB的封装;它的主要优点是易于使用,高速度,低内存开销,和一个小磁盘占用,缺点:开发效率相对不高;
2.既然ADO是一个面向对象的COM,就涉及到一个ADO的对象;
对象图表如下:
对象有:
Connection:用于建立数据源连接;该对象是安全的;
Command:定义一个你打算对数据源执行的特定命令;该对象是不安全的;
Recordset:执行命令生成的结果集或者一个表的记录集;注:纪录集对象始终只有一个记录(当前记录);该对象是安全的;
Parameter:基于参数的名称或者存储过程,主要是存储过程经常用到;
剩下的不常有的对象就不一一介绍了,如果后面有用到,再描述;
3.ADO的重要属性:(全部太多,介绍常用的);
ActiveCommand 指示创建关联的记录集对象的命令对象。
ActiveConnection 指示指定的命令、记录集或记录对象当前所属的连接对象。
bof : 表明当前记录位置在第一条记录前一个记录集对象。
eof : 表明当前记录位置后的最后一个记录一个记录集对象。
CommandText :执行命令语句。
CommandTimeout :表示在执行命令之前要等待多长时间才能终止尝试并生成错误。
CommandType :表示命令对象的类型。
ConnectionTimeout :表示在建立连接之前要等待多长时间才能终止尝试并生成错误。
4.ADO函数:(敲黑板了,重点!!!)
ADO的全部函数并不多,但是我还是不想全部介绍,太懒了,哈哈,有疑问的欢迎留言;
addnew :为一个可更新的记录集对象创建一个新的记录。
例如:recordset.AddNew FieldList, Values;
recordset.update;
Append :附加一个对象集合
BeginTrans:开始一个事务;
commitTrans:提交一个事务;
RollbackTrans:回滚一个事务;
例如:
object.BeginTrans
object.CommitTrans
object.RollbackTrans
cancel :取消执行等待异步方法调用。
例如:
object.Cancel
CreateParameter 创建具有指定属性的新参数对象。(一般会和Append同时出现)
Delete (ADO Parameters Collection):从参数集合中删除一个对象。
Delete (ADO Fields Collection):从字段集合中删除一个对象。
Delete (ADO Recordset):删除结果集;
Excute (ADO Command):执行 CommandText 属性中指定的查询、sql 语句或存储过程。
Excute (ADO Connection)执行指定的查询、sql 语句、存储过程或提供程序特定的文本。
Excute返回一个结果集或者NULL;
Set recordset = command.Execute( RecordsAffected, Parameters, Options ) ;
Getrows 将记录集对象的多个记录检索到数组中。
array = recordset.GetRows(Rows, Start, Fields )
GetString 以字符串形式返回记录集。
Variant = recordset.GetString(StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)
MoveFirst、movelast、movenextMovePrevious:移动到指定 recordset 对象中的第一个、最后一个、下一个或上一个记录, 并将其记录为当前记录。
Open (ADO Connection) :将打开与数据源的连接。
Open (ADO Record) :将打开现有的记录对象, 或创建新的文件或目录。
Open (ADO Recordset) :将打开一个游标。
5.讲了这么多,来一个实例吧;网上将执行SQL语句的很多也很简单,我来一个执行带参数存储过程的;
项目开头:必不可少的;msado15.dll的路径根据自己的情况设置,
#import "C:/Program Files (x86)/Common Files/System/ado/msado15.dll" no_namespace rename("EOF","adoEOF")
_ConnectionPtr m_pConn; //连接
_RecordsetPtr m_pRecordset;//结果集
_CommandPtr m_pCommand;//命令
_RecordsetPtr m_pRecordset;//结果集
_CommandPtr m_pCommand;//命令
初始化:
CoInitializeEx(NULL, COINIT_MULTITHREADED);//初始化COM环境
m_pRecordset.CreateInstance("ADODB.Recordset"); //指针敲出.是不是很神奇,不应该是->吗?
m_pConn.CreateInstance("ADODB.Connect");
m_pCommand.CreateInstance("ADODB.Command");
m_pCommand.CreateInstance("ADODB.Command");
//或者直接这样子:_ConnectionPtr pConn(__uuidof(Connection));初始化也可以;
char sql[] = { "Provider=MSDASQL.1;Persist Security Info=False;User ID=MentoAOI;Data Source=Mento;Initial Catalog=aoi" }; //连接字符串;
HRESULT hr; //连接返回值
try
{
m_pConn->Open(sql, "", "", adConnectUnspecified);
//也可以:m_pConn->ConnectionString = sql; m_pConn->Open("", "", "", adConnectUnspecified);
}
catch (_com_error &e)
{
do
//CString temp = e.Description();
//CString teptemp = e.ErrorMessage();
//ShowDBError(sql, temp, teptemp);
}
if (!SUCCEEDED(hr))
{
CLComLog::GetLogInstance()->sprintfLog(__LINE__, __FILE__, "连接到数据库失败");
return;
}
//CString temp = e.Description();
//CString teptemp = e.ErrorMessage();
//ShowDBError(sql, temp, teptemp);
}
if (!SUCCEEDED(hr))
{
CLComLog::GetLogInstance()->sprintfLog(__LINE__, __FILE__, "连接到数据库失败");
return;
}
接下来:先调一个没有参数的存储过程,再将其执行结果作为参数传到另外一个存储过程去执行;
int GetId(std::string& strIDOut) //返回值表示是否有ID,参数表示具体是多少;
{
char sql[1024] = { 0 };
int iSum = 0;
try
{
sprintf_s(sql, "GetID");
m_pCommand->Cancel();
ParamRefresh(m_pCommand);
m_pCommand->ActiveConnection = m_pConn;//设置链接
m_pCommand->CommandText = sql;//设置命令
m_pCommand->CommandType = adCmdStoredProc;//声明是存储过程
m_pRecordset = m_pCommand->Execute(NULL, NULL, NULL); //执行
m_bUseCommand = true;
m_pRecordset->MoveFirst();//移动到第一行
int iIndex = 0;
char cValue[1024] = { 0 };
_variant_t temp;
if (!m_pRecordset->adoEOF)
{
iIndex = 0;
iSum = 0;
temp = m_pRecordset->GetCollect(_variant_t((long)iIndex));
if (temp.vt != VT_NULL)
{
(iSum) = temp.intVal;
}iIndex++;
int iSum = 0;
try
{
sprintf_s(sql, "GetID");
m_pCommand->Cancel();
ParamRefresh(m_pCommand);
m_pCommand->ActiveConnection = m_pConn;//设置链接
m_pCommand->CommandText = sql;//设置命令
m_pCommand->CommandType = adCmdStoredProc;//声明是存储过程
m_pRecordset = m_pCommand->Execute(NULL, NULL, NULL); //执行
m_bUseCommand = true;
m_pRecordset->MoveFirst();//移动到第一行
int iIndex = 0;
char cValue[1024] = { 0 };
_variant_t temp;
if (!m_pRecordset->adoEOF)
{
iIndex = 0;
iSum = 0;
temp = m_pRecordset->GetCollect(_variant_t((long)iIndex));
if (temp.vt != VT_NULL)
{
(iSum) = temp.intVal;
}iIndex++;
temp = m_pRecordset->GetCollect(_variant_t((long)iIndex))
if (temp.vt != VT_NULL)
{
strcpy_s(cValue, 20, (char*)(_bstr_t)temp.bstrVal);
}
iIndex++;
{
strcpy_s(cValue, 20, (char*)(_bstr_t)temp.bstrVal);
}
iIndex++;
strIDOut =cValue;
}
m_pRecordset->Close();
}
catch (_com_error &e)
{
do;
}
return iSum;
m_pRecordset->Close();
}
catch (_com_error &e)
{
do;
}
return iSum;
}
执行带参数的存储过程;
void GetShopFloorInfo(std::string strID)
{
char sql[1024] = { 0 };
int iSum = 0;
try
{
sprintf_s(sql, "GetIdInfo"); //存储过程名字;
m_pCommand->Cancel();
ParamRefresh(m_pCommand);
m_pCommand->ActiveConnection = m_pConn;
m_pCommand->CommandText = sql;
m_pCommand->CommandType = adCmdStoredProc;
auto pParam = m_pCommand->CreateParameter(_bstr_t("iID"), adVarChar, adParamInput, 20, strID.c_str()); //这几个参数了解存储过程的肯定了解这个吧;
m_pCommand->Parameters->Append(pParam); //加入参数;
CLComLog::GetLogInstance()->sprintfLog(__LINE__, __FILE__, "生成结果集");
m_pRecordset = m_pCommand->Execute(NULL, NULL, NULL);
CLComLog::GetLogInstance()->sprintfLog(__LINE__, __FILE__, "成功生成结果集");
m_bUseCommand = true;
m_pRecordset->MoveFirst();
{
char sql[1024] = { 0 };
int iSum = 0;
try
{
sprintf_s(sql, "GetIdInfo"); //存储过程名字;
m_pCommand->Cancel();
ParamRefresh(m_pCommand);
m_pCommand->ActiveConnection = m_pConn;
m_pCommand->CommandText = sql;
m_pCommand->CommandType = adCmdStoredProc;
auto pParam = m_pCommand->CreateParameter(_bstr_t("iID"), adVarChar, adParamInput, 20, strID.c_str()); //这几个参数了解存储过程的肯定了解这个吧;
m_pCommand->Parameters->Append(pParam); //加入参数;
CLComLog::GetLogInstance()->sprintfLog(__LINE__, __FILE__, "生成结果集");
m_pRecordset = m_pCommand->Execute(NULL, NULL, NULL);
CLComLog::GetLogInstance()->sprintfLog(__LINE__, __FILE__, "成功生成结果集");
m_bUseCommand = true;
m_pRecordset->MoveFirst();
...
..
.
(下面就和没有参数存储过程一样了);
}
}
最后最后:用完记得释放;
if (m_pRecordset)
m_pRecordset->Close(); //关闭记录集
if (m_pConn)
m_pConn->Close();//关闭数据库
if (m_pCommand)
m_pCommand->Cancel();
if (m_pRecordset)
m_pRecordset.Release();//释放记录集对象指针
if (m_pConn)
m_pConn.Release();//释放连接对象指针
CoUninitialize(); //释放COM环境
m_pRecordset->Close(); //关闭记录集
if (m_pConn)
m_pConn->Close();//关闭数据库
if (m_pCommand)
m_pCommand->Cancel();
if (m_pRecordset)
m_pRecordset.Release();//释放记录集对象指针
if (m_pConn)
m_pConn.Release();//释放连接对象指针
CoUninitialize(); //释放COM环境
后面的内容以后再讨论吧!!!