1)引入ADO库定义文件
# import “c:/program files/common files/system/ado/msado15.dll” no_namespace
rename (“EOF”,”adoEOF”)
使得编译的时候,为我们的工程文件生成两个头文件:
msado15.tlh和ado15.tli
注意,msado15.dll的路径可能有所区别,请核对自己的电脑所在的路径
2)初始化COM库
在工程的App类的InitInstance ( )函数里面加上
AfxOleInit ( );//MFC用法
C++的常规方法是--------
:::CoInitialize(NULL);
….
::CoUninitialize();
3)使用记录集对象得到一个纪录集的基本步骤
//生成一个Connection对象,并连结上数据库
_ConnectionPtr m_pConnection;
HRESULT hr;
try
{
hr=m_pConnection.CreateInstance(__uuidof(Connection));
if(SUCCEEDED(hr))
{
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;
Data Source=小学.mdb","","",adModeUnknown);
}
}
catch(_com_error e)
{
CString errormessage;
errormessage.Format("连接数据库失败!/r/n/错误信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
}
//生成RecordSet对象,并得到纪录集
_RecordsetPtr m_pRecordset;
m_pRecordset.CreateInstance("ADODB.Recordset");
CString temp="SELECT * FROM "+tablename;//tablename假设是一个CString类型的表名
_variant_t sql;
sql.SetString(temp);
m_pRecordset->Open(sql,
m_pConnection.GetInterfacePtr( ),
adOpenDynamic,adLockOptimistic,adCmdText );
4)动态查询
CString tablename;
tablename=_T("学籍");
CString temp=_T("SELECT * FROM ")+tablename+_T(" WHERE NAME='")+
dlg.m_name+_T("'");
_variant_t sql;
sql.SetString(temp);
m_pRecordset->Open(sql,m_pConnection.GetInterfacePtr(),
adOpenDynamic,adLockOptimistic,adCmdText);
5)遍历纪录集
int line=0;
while(!m_pRecordset->adoEOF)//遍历记录集,并将所有纪录显示在列表视图中
{
。。。。。。
line++;
m_pRecordset->MoveNext();
}
其余操作都很简单,可以参见其他文章,最关键的是,不要忘了关闭纪录集,因为这通常会造成异常
6)使用ADO连接不同的数据库的方式:
根据不同的数据提供者可以分为ODBC和OLEDB等若干种方式,ODBC兼容性更好,支持OLEDB的数据库相对少一点;
连接SQL Server数据库:
1) Microsoft OLE DB Provider for ODBC
m_pConnection->Open(“Provider=SQLOLEDB.1;DRIVER=SQLServer;SERVER=lzhm;DATABASE=haitang”,"sa","sa",adModeUnknown);
2)未知方法,但是可行,注意Initial Catalog用空格分开
m_pConnection->Open(“Provider=SQLOLEDB.1;Data Source=lzhm;Initial Catalog=haitang”,"sa","sa",adModeUnknown);
m_pConnection->Open ("Provider=SQLOLEDB;Data Source=172.20.2.97;Network Library=DBMSSOCN;Initial Catalog=haitang",”sa”,”sa”,adModeUnknown);
m_pConnection->Open ("Provider=SQLOLEDB;Network Address=172.20.2.97;Initial Catalog=haitang",”sa”,”sa”,adModeUnknown);
m_pConnection->Open ("Provider=SQLOLEDB;Network Address=172.20.2.97; Network Library=DBMSSOCN;Initial Catalog=haitang",”sa”,”sa”,adModeUnknown);
3)Microsoft OLE DB Provider for SQL Server
m_pConnection->Open(“Provider=SQLOLEDB.1;Data Source=lzhm;Initial Catalog=haitang”,"sa","sa",adModeUnknown);
4)不使用DSN进行连接
m_pConnection->Open("driver={SQL Server};server=lzhm;database=haitang”,"sa","sa",adModeUnknown);
连接ACCESS 2000数据库的方式:
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=小学.mdb","","",adModeUnknown);
连接ACCESS 97数据库的方式:
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.3.51;Data Source=小学.mdb","","",adModeUnknown);
7)一个常用的函数,传递一句SQL语句,然后打开一个记录集,假设记录集对象m_pRecordset存在:
BOOL CHaiTangView::GetRecordSet(CString sql)
{//如果生成的记录集不为空,就返回TRUE
if(m_pRecordset->GetState()==1)//如果记录集对象已经打开,则先关闭
m_pRecordset->Close();
HRESULT hr;
_variant_t v_sql;
v_sql.SetString(sql);
try
{
hr=m_pRecordset->Open(v_sql,m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
if(SUCCEEDED(hr))
{
}
}
catch(_com_error e)
{
CString errormessage;
errormessage.Format("查询数据表失败!/r/n错误信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
return 0;
}
m_pRecordset->MoveFirst();
if(!m_pRecordset->adoEOF)//用SUCCEEDED(hr)无法判断记录集的生成是否为空
{ //所以要用生成后的纪录集的最大纪录数是否为0来判别
return TRUE; //SUCCEEDED(hr)应该是来判别异常的,纪录集为空不属于异常
}
else
{
MessageBox("对不起,找不到符合条件的纪录,请联系系统管理员");
return FALSE;
}
}
8)调用Recordset::PutCollect出现的问题:
select 岸线属性表.序号,s1.NAME,岸线属性表.岸线性质,岸线属性表.起点桩号,岸线属性表.终点桩号,岸线属性表.岸线长度,岸线属性表.堤顶高程,岸线属性表.结构形式小类,岸线属性表.结构形式大类,岸线属性表.达标标准,岸线属性表.地域位置,岸线属性表.备注 from 岸线属性表,数据字典表 AS s1 where s1.ID=岸线属性表.岸线名 ORDER BY 岸线属性表.序号
select * from 海塘绿化表 ORDER BY 序号
select 岸线属性表.序号,s1.NAME,s2.NAME from 岸线属性表,数据字典表 AS s1,数据字典表 AS s2 where s1.ID=岸线属性表.岸线名 AND s2.ID=岸线属性表.责任单位 ORDER BY 岸线属性表.序号
在海塘开发的过程中,发现如果使用了RecordSet::Open的方法调用SQL语句打开记录集,如果SQL语句中使用了ORDER BY语句,在使用Recordset::PutCollect方法将数据写入就会出错,至少这是使用VC、ADO和
SQL Server7.0或者2000的情况。
9)调用存储过程,在ATL里面的存储过程
STDMETHODIMP CFBGET::GetDataByProc(BSTR bstrProcName, BSTR bstrParam, BSTR* plPower)
{
// TODO: Add your implementation code here
*plPower = NULL;
USES_CONVERSION;
////////////////////////////////////////////////////////////////////////////
///建立和数据库的连接
_ConnectionPtr m_pCon;
m_pCon.CreateInstance(_uuidof(Connection));
char array[200];
GetWindowsDirectory(array,200);
strcat(array,"//FB_DATA.INI");
char servername[100];
GetPrivateProfileString("ServerName","NAME","",servername,100,array);
char str_con[1024];
wsprintf(str_con,"Provider=SQLOLEDB.1;Data Source=%s;Initial Catalog=haitang;User ID=haitang;PWD=haitang",servername);
m_pCon->Open(str_con,"","",adModeUnknown);
///////////////////////////////////////////////////////////////////////////////
///建立命令对象
_CommandPtr m_pCommand;
m_pCommand.CreateInstance("ADODB.Command");
m_pCommand->ActiveConnection = m_pCon;
_variant_t name="proc_user";
BSTR bname=SysAllocString(OLESTR("proc_user"));
m_pCommand->CommandText=bname;
m_pCommand->CommandType=adCmdStoredProc;
///将参数转换成char*类型,提取出两个char*参数
char *p=W2A(bstrParam);
char* temp=p;
char* p1=temp;
while(*temp!='T')
{
temp++;
}
*temp='/0';
temp++;
char* p2=temp;
while(*temp!='T')
{
temp++;
}
*temp='/0';
//将两个参数转换成BSTR类型
BSTR bstrP1=A2W(p1);
BSTR bstrP2=A2W(p2);
///建立参数对象1
_ParameterPtr p_Param1;
p_Param1.CreateInstance("ADODB.Parameter");
p_Param1->Name="name";
p_Param1->Type=adVarChar;
p_Param1->Size=50;
p_Param1->Direction=adParamInput;
p_Param1->Value=bstrP1;
m_pCommand->Parameters->Append(p_Param1);
///建立参数对象2
_ParameterPtr p_Param2;
p_Param2.CreateInstance("ADODB.Parameter");
p_Param2->Name="key";
p_Param2->Type=adVarChar;
p_Param2->Size=50;
p_Param2->Direction=adParamInput;
p_Param2->Value=bstrP2;
m_pCommand->Parameters->Append(p_Param2);
///建立参数对象3
_bstr_t bstrP3;
_ParameterPtr p_Param3;
p_Param3.CreateInstance("ADODB.Parameter");
p_Param3->Name="power";
p_Param3->Type=adInteger;
p_Param3->Size=10;
p_Param3->Direction=adParamOutput;
// p_Param3->Value=bstrP3; //由于是输出参数,所以千万不能指定Value值
m_pCommand->Parameters->Append(p_Param3);
///执行存储过程,并获得输出参数
m_pCommand->Execute(NULL,NULL,adCmdStoredProc);
_bstr_t value=p_Param3->GetValue();
const char* ppp = value;
*plPower = SysAllocString(A2W(ppp));
return S_OK;
}
注意,如果存储过程里面只写了一个select语句,执行后将返回一个记录集对象,ADO可以通过
m_pRecordet=m_pCommand->Execute (….)来接受,
但是如果存储过程中包含了多个select语句,ADO接受到的记录集对象是不可一使用的。
10)使用命令对象执行SQL语句
_CommandPtr m_pCommand;
m_pCommand.CreateInstance("ADODB.Command");
m_pCommand->ActiveConnection = m_pCon;//m_pCon为数据库连接对象
m_pCommand->CommandText="UPDATE TABLE1 set num_id = '2' WHERE value = '44'";
m_pCommand->CommandType=adCmdText;
m_pCommand->Parameters->Refresh();
///执行存储过程,并获得输出参数
m_pCommand->Execute(NULL,NULL,adCmdUnknown);
11) 得到记录集中字段的数目
m_pRecordset->Fields->GetCount();
也可以通过类似的方式获得字段类型
FieldsPtr fields=m_Rec->GetFields();
* pcActualColSize=fields->GetCount();
VARIANT varIndex;
VariantInit(&varIndex);
varIndex.vt=VT_I4;
FieldPtr field;
DataTypeEnum adoType;
for(long i=0;i<* pcActualColSize;i++)
{
varIndex.lVal=i;
field=fields->GetItem(varIndex);
adoType=field->GetType();
}
下面是类型对应表
enum DataTypeEnum
{ adEmpty = 0,
adTinyInt = 16,
adSmallInt = 2,
adInteger = 3,
adBigInt = 20,
adUnsignedTinyInt = 17,
adUnsignedSmallInt = 18,
adUnsignedInt = 19,
adUnsignedBigInt = 21,
adSingle = 4,
adDouble = 5,
adCurrency = 6,
adDecimal = 14,
adNumeric = 131,
adBoolean = 11,
adError = 10,
adUserDefined = 132,
adVariant = 12,
adIDispatch = 9,
adIUnknown = 13,
adGUID = 72,
adDate = 7,
adDBDate = 133,
adDBTime = 134,
adDBTimeStamp = 135,
adBSTR = 8,
adChar = 129,
adVarChar = 200,
adLongVarChar = 201,
adWChar = 130,
adVarWChar = 202,
adLongVarWChar = 203,
adBinary = 128,
adVarBinary = 204,
adLongVarBinary = 205,
adChapter = 136,
adFileTime = 64,
adPropVariant = 138,
adVarNumeric = 139
} DataTypeEnum;
typedef enum ParameterDirectionEnum
{ dbParamInput = 1,
dbParamOutput = 2,
dbParamInputOutput = 3,
dbParamReturnValue = 4
} ParameterDirectionEnum;