ADO、OLEDB、ODBC之间的关系:
演进路标(从早到晚):ODBC——OLE DB——DAO——RDO——ADO;
OSI模型层次看(非绝对,部分有交叉):最底层数据源——ODBC——OLE DB——RDO、DAO、ADO——应用程序。
一、ODBC
ODBC全称Open Database Connectivity,ODBC建立一组规范(标准),并提供一组对数据库访问的标准API函数接口。ODBC包括ODBC管理器、ODBC API、ODBC驱动管理器、ODBC数据库驱动管理器四个部分。ODBC可以访问应用程序用户具有其ODBC驱动程序的任何本地或远程数据源,一般是以SQL Server、Oracle等关系数据库作为访问对象。如果使用的是基于Microsoft Jet(.mdb)的数据库,使用下面的ADO比Microsoft Access ODBC驱动程序更有效。
二、OLEDB
OLE DB是基于COM技术的一组接口规范,是系统级数据访问接口,OLE DB提供通用数据访问的方式,不管数据是以何种形式存储,可以对电子邮件、文本文件、复合文件、数据表等各种各样的数据通过统一的接口进行存取的一种技术。用来访问各种数据源,如ORACLE、SQL Server、Access、Excel等等。而且相比下文的ADO通用数据访问方 式,OLE DB性能要更强一点。
三、DAO
DAO全称DATA ACCESS OBJECTS,是基于MICROSOFT的JET 技术设计,面向对象的数据访问接口,最早在VB中使用,DAO可以访问的数据库有:
1、用数据库引擎版本为 1.x、2.x 和 3.0 的 Microsoft Access 或 Microsoft Visual Basic 创建的、使用 Microsoft Jet 数据库引擎的数据库。
2、可安装的ISAM 数据库,包括:dBASE III、dBASE IV、dBASE 5.0、Paradox 3.x、4.x 和 5.x 版。
3、开放式数据库连接(ODBC)数据库,包括但不仅限于Microsoft SQL Server、SYBASE SQL Server 和 ORACLE Server。若要访问ODBC数据库,必须具有希望访问的数据库的适当ODBC驱动程序。
4、Microsoft Excel 3.0、4.0、5.0 和 7.0 版工作表。
5、Lotus WKS、WK1、WK3 和 WK4 电子表格。
6、文本文件。
四、RDO
RDO全称Remote Data Objects,翻译就是远程数据对象访问,以ODBC为基础,依赖ODBC API、选定的ODBC 驱动程序以及后端数据库引擎实现大部分的智能和功能,RDO具备基本的ODBC处理方法,所以可以直接执行大多数ODBC API函数。RDO是从DAO派生的,同DAO最大的不同在于其数据库处理模式。DAO是针对Records和Fields,而RDO是按照Rows和Columns来处理。也就是说DAO是ISAM模式,RDO是关系模式。此外DAO是访问Access的Jet引擎 (Jet是ISAM)的接口,而RDO则是访问ODBC的接口。可见,RDO是综合了DAO/Jet、ODBC等优点。
五、ADO
ADO(ACTIVEX DATA OBJECTS)——ADO是基于OLE DB(ActiveX技术)技术设计的应用层数据访问接口,对OLE DB接口进行封装,所以使用中仍然是通过OLE DB桥接数据库。所以,ADO同OEL DB一样提供了通用数据访问功能,支持关系数据库和非关系数据库的访问。ADO功能上对DAO和RDO进行了综合演绎,就是说有合并也有取消优化等等。
实际使用说明:
在实际使用中,我们发现使用ADO访问远程数据库的时候,性能很低,仅仅2万的数据量,如果网络差点,就要花15分钟左右的时间。而在同等条件下OLEDB和ODBC,分别仅需要6秒和5秒。因此如果是远程访问并且要求性能较高的话,推荐使用ODBC。
ODBC文档地址:http://msdn.microsoft.com/en-us/library/windows/desktop/ms714562(v=vs.85).aspx
示例程序:
#include <sql.h> #include <sqlext.h> #include <sqltypes.h>
SQLHENV EnvironmentHandle; RETCODE retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &EnvironmentHandle ); test_retcode( retcode, "SQLAllocHandle(Env) failed!" ); retcode = SQLSetEnvAttr( EnvironmentHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER ); test_retcode( retcode, "SQLSetEnvAttr(ODBC version) Failed" ); SQLHDBC ConnHandle; retcode = SQLAllocHandle( SQL_HANDLE_DBC, EnvironmentHandle, &ConnHandle ); test_retcode( retcode, "Could not allocate MS SQL 2005 connection handle." ); SQLSMALLINT driver_out_length; retcode = SQLDriverConnect( ConnHandle, NULL, // we're not interested in spawning a window (SQLCHAR*) connectstring.c_str(), SQL_NTS, NULL, 0, &driver_out_length, SQL_DRIVER_NOPROMPT ); test_retcode( retcode, "SQLConnect() Failed" ); SQLHSTMT StatementHandle; retcode = SQLAllocHandle(SQL_HANDLE_STMT, ConnHandle, &StatementHandle); test_retcode( retcode, "Failed to allocate SQL Statement handle." ); char* buffer = new char[ MAX_CHAR ]; SQLINTEGER length = MAX_CHAR - 1; // -- Bind Block retcode = SQLExecDirect( StatementHandle, (SQLCHAR*) "SELECT * FROM im_map_ip_op", SQL_NTS ); test_retcode( retcode, "SQLExecDirect failed." ); // -- Fetch Block retcode = SQLBindCol( StatementHandle, 1, SQL_C_CHAR, (SQLPOINTER) NULL, (SQLINTEGER) SQL_DATA_AT_EXEC, &length ); test_retcode( retcode, "Failed to bind column." ); // -- End Bind Block DWORD dw1 = GetTickCount(); int index = 0; while(1) { retcode = SQLFetch( StatementHandle ); if ( retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO && retcode != SQL_NO_DATA ) { printf( "Problem fetching row.\n" ); return 9; } if(retcode ==SQL_NO_DATA_FOUND) { printf( "span time=%d", GetTickCount() -dw1 ); return 9; } memset(buffer, 0x00, length); SQLGetData( StatementHandle, 1, SQL_C_CHAR, buffer, MAX_CHAR, &length ); printf ("index = %d\r\n", index ++); }