众所周知,ANSI-C语言本身并不支持OLE-DB,但是Windows 2000操作系统提供了对OLE-DB的支持。因此,可以通过DLL文件来使CVI语言支持OLE-DB。本文将详细介绍实现这一功能的步骤和方法。
首先,使用向导创建一个MFCDLL项目。然后,需要更新项目中的stdafx.h文件,以包含必要的头文件和宏定义。
#define VC_EXTRALEAN // 排除不常用的内容
#include <afxwin.h> // MFC核心和标准组件
#include <afxext.h> // MFC扩展
#include <afxcview.h> // MFC视图类
#include <afxdisp.h> // MFC自动化类
#include <afxdtctl.h> // MFC支持的Internet Explorer 4公共控件
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF", "adoEOF") // 支持ADO OLE-DB版本2
最后一个语句允许项目支持ADOOLE-DB版本2。接下来,需要定义一个名为cTestCpp的类,该类将执行主要的工作,而testDll.c文件则负责定义接口。
cTestCpp类包含了执行数据库操作所需的所有方法。以下是cTestCpp类的定义和实现。
class cTestCpp {
public:
int Execute(const char *sql, int *AffectedRecord);
int CloseRst(void);
int CloseConn(void);
BOOL IsBof(void);
BOOL IsEof(void);
int GetCount(int *iResult);
int MoveLast(void);
int MoveFirst(void);
int MovePrevious(void);
int Movenext(void);
int openConn(const char *connStr);
void test(void);
int DBConnect(const char *strConn);
int CreateRst(void);
int openRst(const char *sql);
int getCol(const char *colName, int dataType, char *result);
cTestCpp(); // 构造函数
virtual ~cTestCpp(); // 析构函数
private:
_ConnectionPtr m_pConnection; // Ole-DB连接
_RecordsetPtr pRecordSet; // 包含记录的记录集
};
cTestCpp.cpp文件包含了cTestCpp类的具体实现。
#include "stdafx.h"
#include "cTestCpp.h"
#include "msado15.h"
cTestCpp::cTestCpp() {
if (!AfxOleInit()) {
AfxMessageBox("ole Init Error");
return;
}
CoInitialize(NULL);
}
int cTestCpp::DBConnect(const char *strConn) {
return 0;
}
cTestCpp::~cTestCpp() {
CoUninitialize();
}
int cTestCpp::openConn(const char *connStr) {
try {
HRESULT hr = m_pConnection.CreateInstance(__uuidof(Connection));
if (SUCCEEDED(hr)) {
hr = m_pConnection->Open(_bstr_t(connStr), _bstr_t(L""), _bstr_t(L""), adModeUnknown);
return 0;
}
} catch (...) {
return -1;
}
return -1;
}
int cTestCpp::CreateRst() {
HRESULT hr = pRecordSet.CreateInstance(__uuidof(Recordset));
if (SUCCEEDED(hr)) {
return 0;
}
pRecordSet->Release();
return -1;
}
int cTestCpp::openRst(const char *sql) {
_variant_t vRecsAffected(0L);
_bstr_t bstrQuery(sql);
HRESULT hr;
_variant_t vNull;
vNull.vt = VT_ERROR;
vNull.scode = DISP_E_PARAMNOTFOUND;
try {
hr = pRecordSet.CreateInstance(__uuidof(Recordset));
if (SUCCEEDED(hr)) {
pRecordSet->PutRefActiveConnection(m_pConnection);
hr = pRecordSet->Open(_variant_t(bstrQuery), vNull, adOpenForwardOnly, adLockOptimistic, adCmdText);
}
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::getCol(const char *colName, int dataType, char *result) {
try {
_variant_t ss;
CString s;
ss = pRecordSet->GetCollect(colName);
switch (dataType) {
case INTEGER_TYPE:
s.Format("%d", ss.intVal);
break;
case STRING_TYPE:
s = CString(ss.bstrVal);
break;
case DOUBLE_TYPE:
s.Format("%f", ss.dblVal);
break;
case DATE_TYPE:
s.Format("%s", ss.date);
break;
default:
s = "error data type";
}
strcpy(result, (const char*)s);
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::Movenext() {
try {
pRecordSet->MoveNext();
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::MovePrevious() {
try {
pRecordSet->MovePrevious();
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::MoveFirst() {
try {
pRecordSet->MoveFirst();
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::MoveLast() {
try {
pRecordSet->MoveLast();
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::GetCount(int *iResult) {
try {
*iResult = pRecordSet->GetRecordCount();
} catch (...) {
return -1;
}
return 0;
}
BOOL cTestCpp::IsEof(void) {
VARIANT_BOOL bl;
try {
bl = pRecordSet->GetadoEOF();
} catch (...) {
return FALSE;
}
return bl;
}
BOOL cTestCpp::IsBof() {
VARIANT_BOOL bl;
try {
bl = pRecordSet->GetBOF();
} catch (...) {
return FALSE;
}
return bl;
}
int cTestCpp::CloseConn() {
HRESULT hr;
try {
hr = m_pConnection->Close();
m_pConnection.Release();
if (!SUCCEEDED(hr)) {
return -1;
}
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::CloseRst() {
HRESULT hr;
try {
hr = pRecordSet->Close();
pRecordSet.Release();
if (!SUCCEEDED(hr)) {
return -1;
}
} catch (...) {
return -1;
}
return 0;
}
int cTestCpp::Execute(const char *sql, int *AffectedRecord) {
_variant_t vRecsAffected(0L);
_bstr_t bstrQuery(sql);
try {
m_pConnection->Execute(bstrQuery, &vRecsAffected, adOptionUnspecified);
} catch (...) {
return -1;
}
*AffectedRecord = vRecsAffected.intVal;
return 0;
}
#include "stdafx.h"
#include "testDll.h"
#include "cTestCpp.h"
int openConn(const char *connstr) {
return test.openConn(connstr);
}
int CreateRst(void) {
return test.CreateRst();
}
int openRst(const char *sql) {
return test.openRst(sql);
}
int getCol(const char *colName, int dataType, char *result) {
return test.getCol(colName, dataType, result);
}
int movenext() {
return test.MoveNext();
}
int movePrevious() {
return test.MovePrevious();
}
int moveFirst() {
return test.MoveFirst();
}
int moveLast() {
return test.MoveLast();
}
int GetCount(int *iResult) {
return test.GetCount(iResult);
}
BOOL IsEof() {
return test.IsEof();
}
BOOL IsBof() {
return test.IsBof();
}
int closeConn() {
return test.CloseConn();
}
int closeRst() {
return test.CloseRst();
}
int Execute(const char *sql, int *AffectedRecord) {
return test.Execute(sql, AffectedRecord);
}