(一)数据库编程组件间的关系示意图
(二)OLEDB编程基本框架和步骤
接口 IDBCreateSession总接口中CreateSession方法创建Session
对象Session的接口IDBCreateCommand接口中CreateCommand方法创建Command对象
Command对象接口ICommand接口中的Execute()创建Rowset对象。
1DataSource
描述:定义一个环境,数据提供者的一些属性。
2Session
描述:包装一个事物,产生原事物的一个结果集,每个表的字段,主键,约束关系等
3Command
描述:设置一个sql语句,可以执行sql语句,设置参数,属性,得到最终的结果集。
4Rowset
描述:理解为一个结构体的数组(结果集)
(三)数据源对象
数据源对象代表到数据库的一个链接
是使用或链接数据源需要创建的第一个对象
数据源对象提供下面接口
Cotype TDataSource
{
[mandatory] interface IDBCreateSession;
[mandatory] interface IDBInitialize;
[mandatory] interface IDBProperties;
[mandatory] interface IPersist;
[optional] interface IConnectionPointContainer;
[optional] interface IDBAsynchStatus;
[optional] interface IDBDataSourceAdmin;
[optional] interface IDBInfo;
[optional] interface IPersistFile;
[optional] interface ISupportErrorInfo;
}
//[mandatory]强制的,可以理解为基本属性 数据源对象必须提供的,必须实现的 一般
//将接口IDBInitialize作为DataSource对象的标志
//[optional]可选支持的, 不常用
(四)连接到数据源
创建了IDBInitialize接口后,虽然有了数据源对象,但是并不表示已经连接到了数据源上,之后还要设置前述的几个基本属性给数据源对象,以便数据提供者严明正身,提供链接并准备缓冲
①首先需要从IDBInitialize接口Query出IDBProperties接口
②其次准备GUID为DBPROPSET_DBINIT的DBPROPSET结构体和前述几个属性对应值组成的DBPROP数组。
③调用IDBProperties接口的SetProperties方法设置上述属性
④最后调用IDBInitialize的Initialize方法链接到数据库
代码:
#include <tchar.h>
#include <windows.h>
#include <strsafe.h>
#define COM_NO_WINDOWS_H //如果已经包含了Windows.h或不使用其他Windows库函数时
#define OLEDBVER 0x0260 //MSDAC2.6版
#include <oledb.h>
#include <oledberr.h>
#define GRS_ALLOC(sz) HeapAlloc(GetProcessHeap(),0,sz)
#define GRS_CALLOC(sz) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz)
#define GRS_SAFEFREE(p) if(NULL != p){HeapFree(GetProcessHeap(),0,p);p=NULL;}
#define GRS_USEPRINTF() TCHAR pBuf[1024] = {}
#define GRS_PRINTF(...) \
StringCchPrintf(pBuf,1024,__VA_ARGS__);\
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),pBuf,lstrlen(pBuf),NULL,NULL);
#define GRS_SAFERELEASE(I) if(NULL != (I)){(I)->Release();(I)=NULL;}
#define GRS_COM_CHECK(hr,...) if(FAILED(hr)){GRS_PRINTF(__VA_ARGS__);goto CLEAR_UP;}
int _tmain()
{
GRS_USEPRINTF();
CoInitialize(NULL);
HRESULT hr = S_OK;
IDBInitialize* pIDBInitialize = NULL;
IDBProperties* pIDBProperties = NULL;
CLSID clDBSource = {};
hr = CLSIDFromProgID(_T("SQLOLEDB"), &clDBSource);
GRS_COM_CHECK(hr,_T("获取SQLOLEDB的CLSID失败,错误码:0x%08x\n"),hr);
//2、使用纯代码方式连接到指定的数据源
hr = CoCreateInstance(clDBSource, NULL, CLSCTX_INPROC_SERVER,
IID_IDBInitialize,(void**)&pIDBInitialize);
GRS_COM_CHECK(hr,_T("无法创建IDBInitialize接口,错误码:0x%08x\n"),hr);
//准备连接属性
//注意虽然后面只使用了4个属性,但是任然要定义和初始化4+1个属性
//目的是让属性数组最后总有一个空的属性作为数组结尾
DBPROP InitProperties[5] = {};
DBPROPSET rgInitPropSet[1] = {};
//指定数据库实例名,这里使用了别名local,指定本地默认实例
InitProperties[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
InitProperties[0].vValue.vt = VT_BSTR;
InitProperties[0].vValue.bstrVal = SysAllocString(L"ASUS-PC\\SQL2008");
InitProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
InitProperties[0].colid = DB_NULLID;
//指定数据库名
InitProperties[1].dwPropertyID = DBPROP_INIT_CATALOG;
InitProperties[1].vValue.vt = VT_BSTR;
InitProperties[1].vValue.bstrVal = SysAllocString(L"Study");
InitProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
InitProperties[1].colid = DB_NULLID;
// User ID
InitProperties[2].dwPropertyID = DBPROP_AUTH_USERID;
InitProperties[2].vValue.vt = VT_BSTR;
InitProperties[2].vValue.bstrVal = SysAllocString(OLESTR("sa"));
// Password
InitProperties[3].dwPropertyID = DBPROP_AUTH_PASSWORD;
InitProperties[3].vValue.vt = VT_BSTR;
InitProperties[3].vValue.bstrVal = SysAllocString(OLESTR("999999"));
//创建一个GUID为DBPROPSET_DBINIT的属性集合,这也是初始化连接时需要的唯一一个标准属性集合
rgInitPropSet[0].guidPropertySet = DBPROPSET_DBINIT;
rgInitPropSet[0].cProperties = 4;
rgInitPropSet[0].rgProperties = InitProperties;
//得到数据库初始化的属性接口
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties);
GRS_COM_CHECK(hr,_T("获取IDBProperties接口失败,错误码:0x%08x\n"),hr);
hr = pIDBProperties->SetProperties(1, rgInitPropSet);
GRS_COM_CHECK(hr,_T("设置连接属性失败,错误码:0x%08x\n"),hr);
//属性一但设置完成,相应的接口就可以释放了
GRS_SAFERELEASE(pIDBProperties);
//根据指定的属性连接到数据库
hr = pIDBInitialize->Initialize();
GRS_COM_CHECK(hr,_T("使用属性连接到数据源失败,错误码:0x%08x\n"),hr);
GRS_PRINTF(_T("使用属性集方式连接到数据源成功!\n"));
//这里实际上已经拥有了一个正常的数据源对象,可以进一步进行需要的操作
//..................
pIDBInitialize->Uninitialize();
GRS_SAFERELEASE(pIDBInitialize);
CLEAR_UP:
GRS_SAFERELEASE(pIDBProperties);
GRS_SAFERELEASE(pIDBInitialize);
_tsystem(_T("PAUSE"));
CoUninitialize();
return 0;
}
精简一下:(仅仅理解用)
#include <tchar.h>
#include <windows.h>
#include <strsafe.h>
#define COM_NO_WINDOWS_H //如果已经包含了Windows.h或不使用其他Windows库函数时
#define OLEDBVER 0x0260 //MSDAC2.6版
#include <oledb.h>
#include <oledberr.h>
int _tmain()
{
CoInitialize(NULL);
HRESULT hr=S_FALSE;
IDBInitialize* pIDBInitialize=NULL;
IDBProperties* pIDBProperties=NULL;
CLSID clDBSource={};
CLSIDFromProgID(_T("SQLOLEDB"),&clDBSource);
//使用纯代码方式连接到指定的数据源
hr = CoCreateInstance(clDBSource, NULL, CLSCTX_INPROC_SERVER,
IID_IDBInitialize,(void**)&pIDBInitialize);
/*1首先需要从IDBInitialize接口Query出IDBProperties接口*******/
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties);
/*2其次准备GUID为DBPROPSET_DBINIT的DBPROPSET结构体和前述几个属性对应值组成的DBPROP数组***/
DBPROP InitProperties[5] = {};
DBPROPSET rgInitPropSet[1] = {};
//指定数据库实例名,这里使用了别名local,指定本地默认实例
InitProperties[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
InitProperties[0].vValue.vt = VT_BSTR;
InitProperties[0].vValue.bstrVal = SysAllocString(L"YuZhiBo-PC");
InitProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
InitProperties[0].colid = DB_NULLID;
//指定数据库名
InitProperties[1].dwPropertyID = DBPROP_INIT_CATALOG;
InitProperties[1].vValue.vt = VT_BSTR;
InitProperties[1].vValue.bstrVal = SysAllocString(L"scott");
InitProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
InitProperties[1].colid = DB_NULLID;
// User ID
InitProperties[2].dwPropertyID = DBPROP_AUTH_USERID;
InitProperties[2].vValue.vt = VT_BSTR;
InitProperties[2].vValue.bstrVal = SysAllocString(OLESTR("sa"));
// Password
InitProperties[3].dwPropertyID = DBPROP_AUTH_PASSWORD;
InitProperties[3].vValue.vt = VT_BSTR;
InitProperties[3].vValue.bstrVal = SysAllocString(OLESTR("tiger"));
//创建一个GUID为DBPROPSET_DBINIT的属性集合,这也是初始化连接时需要的唯一一个标准属性集合
rgInitPropSet[0].guidPropertySet = DBPROPSET_DBINIT;
rgInitPropSet[0].cProperties = 4;
rgInitPropSet[0].rgProperties = InitProperties;
/*3调用IDBProperties接口的SetProperties方法设置上述属性****/
hr = pIDBProperties->SetProperties(1, rgInitPropSet);
/*4最后调用IDBInitialize的Initialize方法链接到数据库*********/
hr=pIDBInitialize->Initialize();
pIDBInitialize->Uninitialize();
return 0;
}