用ATL OLEDB访问数据库.docx
- 文档编号:24638400
- 上传时间:2023-05-29
- 格式:DOCX
- 页数:19
- 大小:20.42KB
用ATL OLEDB访问数据库.docx
《用ATL OLEDB访问数据库.docx》由会员分享,可在线阅读,更多相关《用ATL OLEDB访问数据库.docx(19页珍藏版)》请在冰豆网上搜索。
用ATLOLEDB访问数据库
用ATLOLEDB访问数据库
在Windows系统上访问数据库,除了数据库自身带的专用访问库,如SQLServer/Sybase的DBLibrary以及Oracle的PRO*C等,其他流行的通用访问组件主要就是ODBC,JDBC,OLEDB等几种了。
其中ODBC是最早出现的通用访问组件,比较传统,在C/C++程序中使用较多。
至于DAO、RDO仅为VisualBASIC服务的。
ADO在OLEDB基础上做的,由于使用简单,在VisualBASIC和ASP等脚本类程序中使用较多。
JDBC是JAVA语言实现的类似ODBC的数据库访问组件。
OLEDB是基于COM接口的,同时支持关系数据库和非关系型数据源,功能强大而复杂。
主要面向C/C++群体,正是由于直接使用OLEDB的复杂性,使用者不多。
而基于OLEDB的ADO由于更加高级、简单,而得到了一部分VB、WEB程序员的青睐。
ATL以更加容易使用的模板类封装了OLEDB的COM接口。
使用起来不比ODBC复杂多少,可以作为ODBC的一种替代访问方式。
下面的代码试图在ATL基础上简单封装,以达到让访问数据库更简单的目的。
#ifndef__COMMDB_H_
#define__COMMDB_H_
#include
externCComModule_Module;
#include
#include
#include
/************************************************************************
RemarksonCCommDB:
ParameterDsnProgIdofOpenDataSourcecanbeoneofbelow:
"MSDASQL"--forOLEDB-ODBCBridge
"SQLOLEDB"--forMicrosoftSQLServer
"OraOLEDB.Oracle"--forOracle8i,9i,10g,etc...
"Sybase.ASEOLEDBProvider"--forSybaseASE
************************************************************************/
classCCommDB
{
public:
CCommDB(){}
virtual~CCommDB(){}
BOOLOpenDataSource(
LPCSTRDsnProgId,
LPCSTRDataSource,
LPCSTRCatalog,
LPCSTRUserID,
LPCSTRPassword)
{
USES_CONVERSION;
CDBPropSetinit(DBPROPSET_DBINIT);
init.AddProperty(DBPROP_INIT_DATASOURCE,A2OLE(DataSource));
init.AddProperty(DBPROP_INIT_CATALOG,A2OLE(Catalog));
init.AddProperty(DBPROP_AUTH_USERID,A2OLE(UserID));
init.AddProperty(DBPROP_AUTH_PASSWORD,A2OLE(Password));
init.AddProperty(DBPROP_INIT_LCID,(long)2052);
init.AddProperty(DBPROP_INIT_PROMPT,(short)4);
HRESULThr=m_DB.Open(DsnProgId,&init);
if(!
SUCCEEDED(hr))
returnFALSE;
hr=m_Session.Open(m_DB);
if(!
SUCCEEDED(hr))
returnFALSE;
returnTRUE;
}
BOOLDisConnect()
{
m_Session.Close();//DonotforgettocloseCSessionandCDataSource
m_DB.Close();
returnTRUE;
}
CSession&GetSession()
{
returnm_Session;
}
CDataSource&GetDataSource()
{
returnm_DB;
}
private:
CSessionm_Session;
CDataSourcem_DB;
};
template
classCCommSQL
{
public:
CCommSQL(CSession&Session):
m_Session(Session)
{
}
virtual~CCommSQL()
{
m_Command.Close();
}
public:
BOOLExecuteCommand(LPCSTRszCommand)
{
m_Command.Close();//Mustcleanrowsetfirst.
HRESULThr=m_Command.Open(m_Session,szCommand);
if(!
SUCCEEDED(hr))
returnFALSE;
returnTRUE;
}
public:
template
voidGetValue(intnColumn,ctype*pData)
{
m_Command.GetValue(nColumn,pData);
}
template
voidGetValue(char*szColumn,ctype*pData)
{
m_Command.GetValue(szColumn,pData);
}
void*GetValue(intnColumn)//returnsomespecialtype'svalue,suchasstring.
{
DBSTATUSStatus;
boolbRet=m_Command.GetStatus(nColumn,&Status);
if(!
bRet)//thespecifiedcolumnisnotfound.
returnNULL;
if(Status==DBSTATUS_S_ISNULL)
returnNULL;
else//if(Status==DBSTATUS_S_OK||Status==DBSTATUS_S_TRUNCATED)orerror.
returnm_Command.GetValue(nColumn);
}
void*GetValue(char*szColumn)//returnsomespecialtype'svalue,suchasstring.
{
DBSTATUSStatus;
boolbRet=m_Command.GetStatus(szColumn,&Status);
if(!
bRet)//thespecifiedcolumnisnotfound.
returnNULL;
if(Status==DBSTATUS_S_ISNULL)
returnNULL;
else//if(Status==DBSTATUS_S_OK||Status==DBSTATUS_S_TRUNCATED)orerror.
returnm_Command.GetValue(szColumn);
}
public:
BOOLMoveFirst()
{
HRESULThr=m_Command.MoveFirst();
if(!
SUCCEEDED(hr)||hr==DB_S_ENDOFROWSET)
returnFALSE;
returnTRUE;
}
BOOLMoveNext()
{
HRESULThr=m_Command.MoveNext();
if(!
SUCCEEDED(hr)||hr==DB_S_ENDOFROWSET)
returnFALSE;
returnTRUE;
}
public:
BOOLGetColumnType(ULONGnColumn,DBTYPE*pType)
{
returnm_Command.GetColumnType(nColumn,pType)?
TRUE:
FALSE;
}
ULONGGetColumnCount()
{
returnm_Command.GetColumnCount();
}
LPSTRGetColumnName(ULONGnColumn,LPSTRszColumn,DWORDdwBufferSize)
{
USES_CONVERSION;
LPOLESTRszOle=m_Command.GetColumnName(nColumn);
if(szOle==NULL)
returnNULL;
ATLASSERT(dwBufferSize);
if(dwBufferSize==0)
returnNULL;
strncpy(szColumn,OLE2A(szOle),dwBufferSize-1);
szColumn[dwBufferSize-1]='\0';
returnszColumn;
}
public:
BOOLGetNextResult()
{
LONGRowsAffected;
HRESULThr=m_Command.GetNextResult(&RowsAffected);
if(!
SUCCEEDED(hr))
returnFALSE;
returnTRUE;
}
private:
CSession&m_Session;
CCommand
};
/************************************************************************/
/*Helpermacros,replace"abc'd"to"'abc''d'".*/
/************************************************************************/
inlineintSQLStrLen(LPCSTRszId,CHARcSpecialChar)
{
intIdLen=0;
LPCSTRp=szId;
while(*p)
{
if(*p==cSpecialChar)
IdLen++;
IdLen++;
p++;
}
returnIdLen;
}
inlineLPCSTRToSQL(LPCSTRszId,CHARcSpecialChar,LPSTRszNewId)
{
LPCSTRp;
LPSTRpNew;
if(!
szNewId)
returnNULL;
p=szId;
pNew=szNewId;
//AddfirstcSpecialChar,suchas'
*pNew++=cSpecialChar;
while(*p)
{
if(*p==cSpecialChar)
{
*pNew++=cSpecialChar;
*pNew=*p;
}
*pNew++=*p++;
}
//AddlastcSpecialChar,suchas'
*pNew++=cSpecialChar;
*pNew='\0';
returnszNewId;
}
#defineUSES_SQLintDestLen;DestLen
//SQLIDfor[]
#defineSQLID(szId)(\
(szId==NULL)?
"NULL":
(\
DestLen=(SQLStrLen(szId,']')+3),\
ToSQL(szId,']',(LPSTR)alloca(DestLen))))
//SQLIDfor""
#defineSQLID2(szId)(\
(szId==NULL)?
"NULL":
(\
DestLen=(SQLStrLen(szId,'"')+3),\
ToSQL(szId,'"',(LPSTR)alloca(DestLen))))
//SQLString''
#defineSQLSTR(szId)(\
(szId==NULL)?
"NULL":
(\
DestLen=(SQLStrLen(szId,'\'')+3),\
ToSQL(szId,'\'',(LPSTR)alloca(DestLen))))
#endif//__COMMDB_H_
使用起来很简单,下面是示范代码,通过OLEDB-ODBC桥接的方式访问一个文本数据库test.txt,其中有两个字段:
IndexInteger,NameChar20。
访问其他的数据库也是同样的,只需要事先建好OLEDB数据源即可。
#define_WIN32_DCOM
#include"commdb.h"
#include
#include
CComModule_Module;
staticCCommDB*g_pDB=NULL;
staticCCommSQL
staticCCommSQL
staticCRITICAL_SECTIONSQLExecuteLock;
#defineDSN_PROGID"MSDASQL"
#defineDSN_NAME"test.txt"
#defineDSN_DATABASE""
#defineDSN_USERNAME""
#defineDSN_PASSWORD""
EXTERN_CBOOLConnectDB()
{
HRESULThr=CoInitializeEx(NULL,0);
if(FAILED(hr))
returnFALSE;
g_pDB=newCCommDB;
if(g_pDB==NULL)
{
CoUninitialize();
returnFALSE;
}
BOOLbRet=g_pDB->OpenDataSource(DSN_PROGID,DSN_NAME,DSN_DATABASE,
DSN_USERNAME,DSN_PASSWORD);
if(!
bRet)
{
deleteg_pDB;
g_pDB=NULL;
CoUninitialize();
returnFALSE;
}
g_pRsCmd=newCCommSQL
(g_pDB->GetSession());
if(g_pRsCmd==NULL)
{
deleteg_pDB;
g_pDB=NULL;
CoUninitialize();
returnFALSE;
}
g_pCmd=newCCommSQL
(g_pDB->GetSession());
if(g_pCmd==NULL)
{
deleteg_pDB;
g_pDB=NULL;
deleteg_pRsCmd;
g_pRsCmd=NULL;
CoUninitialize();
returnFALSE;
}
InitializeCriticalSection(&SQLExecuteLock);
returnTRUE;
}
EXTERN_CVOIDDisConnectDB()
{
deleteg_pRsCmd;
g_pRsCmd=NULL;
deleteg_pCmd;
g_pCmd=NULL;
g_pDB->DisConnect();
deleteg_pDB;
g_pDB=NULL;
CoUninitialize();
DeleteCriticalSection(&SQLExecuteLock);
}
#defineMAX_SQL_LEN1024
BOOLInsert(INTIndex,LPCSTRName)
{
charsql[MAX_SQL_LEN];
USES_SQL;
BOOLbRet;
_ASSERT(g_pDB);
_ASSERT(g_pCmd);
if(g_pDB==NULL||g_pCmd==NULL)
returnFALSE;
sprintf(sql,
"INSERTINTO[test.txt]([INDEX],[NAME])VALUES(%d,%s)",
Index,
SQLSTR(Name));
EnterCriticalSection(&SQLExecuteLock);
bRet=g_pCmd->ExecuteCommand(sql);
LeaveCriticalSection(&SQLExecuteLock);
returnbRet;
}
BOOLSelect()
{
charsql[MAX_SQL_LEN];
USES_SQL;
BOOLbRet;
_ASSERT(g_pDB);
_ASSERT(g_pRsCmd);
if(g_pDB==NULL||g_pRsCmd==NULL)
returnFALSE;
sprintf(sql,"SELECT*FROM[test.txt]");
EnterCriticalSection(&SQLExecuteLock);
bRet=g_pRsCmd->ExecuteCommand(sql);
if(!
bRet)
{
LeaveCriticalSection(&SQLExecuteLock);
returnFALSE;
}
while(g_pRsCmd->MoveNext())
{
INTIndex;
LPCSTRName;
g_pRsCmd->GetValue("INDEX",&Index);
Name=(LPCSTR)g_pRsCmd->GetValue("NAME");
printf("Index:
%d\tName:
%s\n",Index,Name);
}
LeaveCriticalSection(&SQLExecuteLock);
returnbRet;
}
intmain(intargc,char*argv[])
{
BOOLbRet=ConnectDB();
if(!
bRet)
{
printf("Connectdatabasefailed.\n");
return-1;
}
Insert(0,"Fang");
Insert(1,"ab'c");
Select();
DisConnectDB();
return0;
}
如果访问数据库的代码仅在一个线程中执行,也可以去掉上面的同步执行锁。
上面的代码仅仅演示ATLOLEDB的简单应用,更深入的使用方法需要用户进一步了解OLEDB的文档,这些就不在本文的讨论范围当中了。
附:
用程序设置OLEDBDSN的方法
设置OLEDB数据源,可以使用数据库提供的工具手工配置。
也可以在程序中自动配置,这样不必事先设置好数据源,仅需要给出数据库的一些基本信息就可以访问了。
a)SQLServer
可以在注册表中用程序设置DSN。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo
添加REG_SZ类型值,格式:
dsn_name=DBMSSOCN,host_ip[,server_port]
例如:
SqlServer=DBMSSOCN,192.168.0.1
或者:
SqlServer=DBMSSOCN,192.168.0.1,1433
a)Oracle
首先从注册表中找出OracleHome目录。
以Oracle10gclient来说,就是
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient10g_home1
在此键下读取ORACLE_HOME值,注意:
Oracle的其他版本如Oracle8i,Oracle9i的注册表结构有些不同。
然后,到OracleHome目录下的network\ADMIN\tnsnames.ora文件中设置DSN,格式为:
DSN_NAME=
(DESCRIPTION=
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST=HOST_IP)(PORT=SERVER_PORT))
)
(CONNECT_DATA=
(SERVICE_NAME=SERVICE_NAME)
)
)
例如
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 用ATL OLEDB访问数据库 ATL OLEDB 访问 数据库