使用com访问SQL SERVER,该如何把ADO加到com?csdn不能搜索,只好自己问了, 能捎带介绍一下ATL的资料,感激不尽! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我现在作一b/s系统,使用asp,访问sql的时候有点困惑,不知到是该使用com,还是直接使用script.一来对com不熟悉,有点困难,二来不知道能否不用com,而是作一script文件实现com所提供的接口,用的时候仅仅include一下。如果可行的话具体如何操作呢? Sure! MSDN ATL and ADO. 随便找一本VC中使用ADO的例子看看,在ATL中使用的方法一样。我的一个例子:// StationINFO.h: interface for the CStationINFO class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_STATIONINFO_H__20B3282D_488E_49AF_908D_BA06605FBD39__INCLUDED_)#define AFX_STATIONINFO_H__20B3282D_488E_49AF_908D_BA06605FBD39__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000//ADO#define INITGUID#import "E:\program files\common files\system\ado\msado15.dll" rename ("EOF","adoEOF") no_namespace#include <icrsint.h>#define CREATEiNSTANCE(sp,riid) { HRESULT _hr =sp .CreateInstance( __uuidof( riid ) ); \ if (FAILED(_hr)) _com_issue_error(_hr); }#define RsITEM(rs,x) rs->Fields->Item[_variant_t(x)]->Value#define UC (_TCHAR *)typedef struct tagStation{ _TCHAR StatID[6]; _TCHAR StatName[20]; INT ProvinceID; _TCHAR Canton[10]; FLOAT Longitude; FLOAT Latitude; FLOAT Altitude; FLOAT ShowLevel; //显示级别}StationTable;typedef struct tagProvince{ INT ID; _TCHAR Province[10];}ProvinceTable;class CStationRS: public CADORecordBinding{ BEGIN_ADO_BINDING(CStationRS) //ADO_NUMERIC_ENTRY2(Ordinal, DataType, Buffer, Precision, Scale, Modify) //ADO_VARIABLE_LENGTH_ENTRY2(Ordinal, DataType, Buffer, Size, Status, Modify) ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, StatID,sizeof(StatID), StatID_Status, false) ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, StatName,sizeof(StatName), StatName_Status, false) ADO_NUMERIC_ENTRY2(4, adInteger, ProvinceID,5, 0, false) ADO_VARIABLE_LENGTH_ENTRY2(5, adVarChar, Canton,sizeof(Canton), Canton_Status, false) ADO_NUMERIC_ENTRY2(6, adSingle, Latitude,8, 2, false) ADO_NUMERIC_ENTRY2(7, adSingle, Longitude,8,2, false) ADO_NUMERIC_ENTRY2(8, adSingle, Altitude,8, 2, false) ADO_NUMERIC_ENTRY2(9, adSingle, ShowLevel,8,2, false) END_ADO_BINDING()public: _TCHAR StatID[6]; ULONG StatID_Status; //记录对应错误代码 _TCHAR StatName[20]; ULONG StatName_Status; //记录对应错误代码 INT ProvinceID; ULONG ProvinceID_Status; //记录对应错误代码 _TCHAR Canton[10]; ULONG Canton_Status; //记录对应错误代码 FLOAT Longitude; ULONG Longitude_Status; //记录对应错误代码 FLOAT Latitude; ULONG Latitude_Status; //记录对应错误代码 FLOAT Altitude; ULONG Altitude_Status; //记录对应错误代码 FLOAT ShowLevel; //显示级别 ULONG ShowLevel_Status; //记录对应错误代码};class CStationINFO{public: CStationINFO(); virtual ~CStationINFO(); StationTable *cpStations; ProvinceTable *cpProvince; INT StationCount; INT ProvinceCount; INT GetInfoFromDB(); BOOL GetInfoStd();private: BOOL InfoStd;};#endif // !defined(AFX_STATIONINFO_H__20B3282D_488E_49AF_908D_BA06605FBD39__INCLUDED_)____________________________________________________________________________________________________________________________________________________________________// StationINFO.cpp: implementation of the CStationINFO class.////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "StationINFO.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;//#define new DEBUG_NEW#endif//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CStationINFO::CStationINFO():cpProvince(NULL),cpStations(NULL),InfoStd(FALSE){ //MessageBox(NULL,_T("StdInfo"),_T("Enter"),MB_OK); //读取数据由CMIDView构造函数执行}INT CStationINFO::GetInfoFromDB(){ MessageBox(NULL,_T("Getting Stdinfo"),_T(""),MB_OK); _RecordsetPtr spRS; _ConnectionPtr spCON; try{ CREATEiNSTANCE(spCON,Connection); spCON->ConnectionString =_Module.DBCLIENTCONNSTR; spCON->Open("","","", -1 ); CREATEiNSTANCE(spRS,Recordset) spRS->PutRefActiveConnection(spCON ); spRS->Open("select * from [StationInfo]", vtMissing,adOpenKeyset, adLockBatchOptimistic, adCmdUnspecified); HRESULT hr; IADORecordBinding *picRS; //指向COM接口的指针 CStationRS rs; if(FAILED(hr=spRS->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRS))) //接口IADORecordBinding是记录集的一部分 _com_issue_error(hr); if(FAILED(hr=picRS->BindToRecordset(&rs)))_com_issue_error(hr); //绑定到记录集 if (spRS->RecordCount>0) { spRS->MoveLast(); spRS->MoveFirst(); StationCount=spRS->RecordCount; cpStations=new StationTable[StationCount]; StationTable *pStations=cpStations; while(spRS->adoEOF == false){ _tcscpy((_TCHAR *)pStations->StatName,rs.StatName_Status==adFldOK?rs.StatName:_T("")); _tcscpy((_TCHAR *)pStations->StatID,rs.StatID_Status==adFldOK?rs.StatID:_T("")); _tcscpy((_TCHAR *)pStations->Canton,rs.Canton_Status==adFldOK?rs.Canton:_T("")); pStations->Altitude =rs.Altitude; pStations->Latitude =rs.Latitude*1000.f; pStations->Longitude =rs.Longitude*1000.f; pStations->ProvinceID =rs.ProvinceID; pStations->ShowLevel =rs.ShowLevel; ATLTRACE(_T("%S,%S,%S\n"),rs.StatName,rs.StatID,rs.Canton ); spRS->MoveNext(); pStations++; } spRS->Close(); } spCON->Close(); InfoStd=TRUE; return 1; } catch( _com_error &e) { _bstr_t bstrSource(e.Source()); _bstr_t bs = _bstr_t(" Error: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ") + _bstr_t(e.Description()); MessageBox(0,bs,bstrSource, MB_OK); InfoStd=FALSE; return 0; } }BOOL CStationINFO::GetInfoStd(){ return InfoStd;}CStationINFO::~CStationINFO(){ if(cpProvince!=NULL)delete [] cpProvince; if(cpStations!=NULL)delete [] cpStations; //MessageBox(NULL,_T("Stdinfo"),_T("leave"),MB_OK);}#undef UC #import "C:\Program Files\Common Files\SYSTEM\ADO\MSADO15.DLL" no_namespace rename("EOF","ADOEOF") 直接在IDL文件中导入msado15.idl文件import "msado15.idl"然后就可以用_Connection _Recordset来定义变量了 我感觉你的困惑是对com功能定位上. 现在谈的三层构架解决方案 com就能很好的担任中间层--商业逻辑层.比如你当前的b/s系统:web是表示层,用来接收客户信息并返回数据信息.商业逻辑层,在国外你会见到大多是用一系列组件来处理,它负责于个分布式的 数据库大交道,负责提供各种接口供表示层调取.一些安全性高或大型的系统,常是这种路子. 以前国内的b/s通常是asp代码担任了逻辑层的角色,这样做简单,快捷,但安全性能相对薄弱. 比方人家读破你的asp,那你的数据库服务器就裸露待人攻击了.而若是你用组件来替代相关的asp代码,效果不言而寓,象招商银行就是这么干的.使用ado:atl的接口文件(.idl) 你可不用去管它,在stdafx.h中,象上面的虾哥虾弟们那样:#import "C:\Program Files\Common Files\SYSTEM\ADO\MSADO15.DLL" no_namespace rename("EOF","ADOEOF")然后在接口函数实现里,调用ado就成,具体方法搜下坛子. 谢谢大家。对于bojinyu(沙鱼) 的代码,我正在研究,感谢您的慷慨。to fanchka(狼仔) :您的感觉非常正确,我实际上是得到了一套b/s系统,数据库结构和script代码都有,但是其逻辑层正如您所说,使用了dll,我现在想偷懒:),借鉴其数据库和script代码开发自己的系统,但是在怎么实现逻辑层上有困惑。能不能用别的办法代替dll,而不需要大的改动script呢?安全方面暂且放在一边。因为对开发dll确实是一窍不通。一定会给几位加分的。分数不够我就再开帖子:) to: royya(阿瑟)dll的实质,你就可以把它当作一些函数的集合. 调用dll,调用接口方法,就如同调用集合中的函数一样,没什么太奇妙的. 如果,你想通过脚本来替代dll的逻辑,没什么好的方法,查看接口的实现代码,再把他的思路转成脚本代码. 呵呵,我说的都感到麻烦,你做的怕更要烦. 若是系统小,这样子该是可以,若是系统大,那你可要和老板多蹭点时间.good luck. 南京有培训vc的地方吗 CTabView中标签的切换按钮无法响应的问题。求高手 CreateBitmap图片时怎么生成指定RGB颜色的图片呀 如何在系统菜单栏上添加按钮 关于U盘的一些问题! 如何计算程序的空闲时间? 如何给CEditCtrl设置颜色? 如何找出本进程内所有的窗口? 大侠请进! 如何把一个工程文件中的对话框加到另一个工程文件中? 各位高手!求教FlexGrid的问题。100分相送!!! 一个剧牛程序
我的一个例子:// StationINFO.h: interface for the CStationINFO class.
//
//////////////////////////////////////////////////////////////////////#if !defined(AFX_STATIONINFO_H__20B3282D_488E_49AF_908D_BA06605FBD39__INCLUDED_)
#define AFX_STATIONINFO_H__20B3282D_488E_49AF_908D_BA06605FBD39__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000//ADO
#define INITGUID
#import "E:\program files\common files\system\ado\msado15.dll" rename ("EOF","adoEOF") no_namespace
#include <icrsint.h>#define CREATEiNSTANCE(sp,riid) { HRESULT _hr =sp .CreateInstance( __uuidof( riid ) ); \
if (FAILED(_hr)) _com_issue_error(_hr); }
#define RsITEM(rs,x) rs->Fields->Item[_variant_t(x)]->Value
#define UC (_TCHAR *)typedef struct tagStation
{
_TCHAR StatID[6];
_TCHAR StatName[20];
INT ProvinceID;
_TCHAR Canton[10];
FLOAT Longitude;
FLOAT Latitude;
FLOAT Altitude;
FLOAT ShowLevel; //显示级别
}StationTable;typedef struct tagProvince
{
INT ID;
_TCHAR Province[10];
}ProvinceTable;class CStationRS: public CADORecordBinding
{
BEGIN_ADO_BINDING(CStationRS)
//ADO_NUMERIC_ENTRY2(Ordinal, DataType, Buffer, Precision, Scale, Modify)
//ADO_VARIABLE_LENGTH_ENTRY2(Ordinal, DataType, Buffer, Size, Status, Modify)
ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, StatID,sizeof(StatID), StatID_Status, false)
ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, StatName,sizeof(StatName), StatName_Status, false)
ADO_NUMERIC_ENTRY2(4, adInteger, ProvinceID,5, 0, false)
ADO_VARIABLE_LENGTH_ENTRY2(5, adVarChar, Canton,sizeof(Canton), Canton_Status, false)
ADO_NUMERIC_ENTRY2(6, adSingle, Latitude,8, 2, false)
ADO_NUMERIC_ENTRY2(7, adSingle, Longitude,8,2, false)
ADO_NUMERIC_ENTRY2(8, adSingle, Altitude,8, 2, false)
ADO_NUMERIC_ENTRY2(9, adSingle, ShowLevel,8,2, false)
END_ADO_BINDING()
public:
_TCHAR StatID[6];
ULONG StatID_Status; //记录对应错误代码
_TCHAR StatName[20];
ULONG StatName_Status; //记录对应错误代码
INT ProvinceID;
ULONG ProvinceID_Status; //记录对应错误代码
_TCHAR Canton[10];
ULONG Canton_Status; //记录对应错误代码
FLOAT Longitude;
ULONG Longitude_Status; //记录对应错误代码
FLOAT Latitude;
ULONG Latitude_Status; //记录对应错误代码
FLOAT Altitude;
ULONG Altitude_Status; //记录对应错误代码
FLOAT ShowLevel; //显示级别
ULONG ShowLevel_Status; //记录对应错误代码
};class CStationINFO
{
public:
CStationINFO();
virtual ~CStationINFO();
StationTable *cpStations;
ProvinceTable *cpProvince;
INT StationCount;
INT ProvinceCount; INT GetInfoFromDB();
BOOL GetInfoStd();private:
BOOL InfoStd;
};#endif // !defined(AFX_STATIONINFO_H__20B3282D_488E_49AF_908D_BA06605FBD39__INCLUDED_)____________________________________________________________________________________________________________________________________________________________________// StationINFO.cpp: implementation of the CStationINFO class.
//
//////////////////////////////////////////////////////////////////////#include "stdafx.h"
#include "StationINFO.h"#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
//#define new DEBUG_NEW
#endif//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////CStationINFO::CStationINFO():cpProvince(NULL),cpStations(NULL),InfoStd(FALSE)
{
//MessageBox(NULL,_T("StdInfo"),_T("Enter"),MB_OK);
//读取数据由CMIDView构造函数执行
}INT CStationINFO::GetInfoFromDB()
{
MessageBox(NULL,_T("Getting Stdinfo"),_T(""),MB_OK);
_RecordsetPtr spRS;
_ConnectionPtr spCON;
try{
CREATEiNSTANCE(spCON,Connection);
spCON->ConnectionString =_Module.DBCLIENTCONNSTR;
spCON->Open("","","", -1 );
CREATEiNSTANCE(spRS,Recordset)
spRS->PutRefActiveConnection(spCON );
spRS->Open("select * from [StationInfo]", vtMissing,adOpenKeyset,
adLockBatchOptimistic, adCmdUnspecified);
HRESULT hr;
IADORecordBinding *picRS; //指向COM接口的指针
CStationRS rs; if(FAILED(hr=spRS->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRS))) //接口IADORecordBinding是记录集的一部分
_com_issue_error(hr);
if(FAILED(hr=picRS->BindToRecordset(&rs)))_com_issue_error(hr); //绑定到记录集 if (spRS->RecordCount>0)
{
spRS->MoveLast();
spRS->MoveFirst();
StationCount=spRS->RecordCount;
cpStations=new StationTable[StationCount];
StationTable *pStations=cpStations; while(spRS->adoEOF == false){
_tcscpy((_TCHAR *)pStations->StatName,rs.StatName_Status==adFldOK?rs.StatName:_T(""));
_tcscpy((_TCHAR *)pStations->StatID,rs.StatID_Status==adFldOK?rs.StatID:_T(""));
_tcscpy((_TCHAR *)pStations->Canton,rs.Canton_Status==adFldOK?rs.Canton:_T(""));
pStations->Altitude =rs.Altitude;
pStations->Latitude =rs.Latitude*1000.f;
pStations->Longitude =rs.Longitude*1000.f;
pStations->ProvinceID =rs.ProvinceID;
pStations->ShowLevel =rs.ShowLevel;
ATLTRACE(_T("%S,%S,%S\n"),rs.StatName,rs.StatID,rs.Canton );
spRS->MoveNext();
pStations++;
}
spRS->Close();
} spCON->Close();
InfoStd=TRUE;
return 1;
}
catch( _com_error &e)
{
_bstr_t bstrSource(e.Source());
_bstr_t bs = _bstr_t(" Error: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ")
+ _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ")
+ _bstr_t(e.Description());
MessageBox(0,bs,bstrSource, MB_OK);
InfoStd=FALSE;
return 0;
}
}BOOL CStationINFO::GetInfoStd()
{
return InfoStd;
}CStationINFO::~CStationINFO()
{
if(cpProvince!=NULL)delete [] cpProvince;
if(cpStations!=NULL)delete [] cpStations;
//MessageBox(NULL,_T("Stdinfo"),_T("leave"),MB_OK);
}
#undef UC
import "msado15.idl"
然后就可以用_Connection _Recordset来定义变量了
现在谈的三层构架解决方案 com就能很好的担任中间层--商业逻辑层.
比如你当前的b/s系统:
web是表示层,用来接收客户信息并返回数据信息.
商业逻辑层,在国外你会见到大多是用一系列组件来处理,它负责于个分布式的
数据库大交道,负责提供各种接口供表示层调取.
一些安全性高或大型的系统,常是这种路子.
以前国内的b/s通常是asp代码担任了逻辑层的角色,这样做简单,快捷,但安全性
能相对薄弱. 比方人家读破你的asp,那你的数据库服务器就裸露待人攻击了.
而若是你用组件来替代相关的asp代码,效果不言而寓,象招商银行就是这么干的.
使用ado:
atl的接口文件(.idl) 你可不用去管它,在stdafx.h中,象上面的虾哥虾弟们那样:
#import "C:\Program Files\Common Files\SYSTEM\ADO\MSADO15.DLL" no_namespace rename("EOF","ADOEOF")然后在接口函数实现里,调用ado就成,具体方法搜下坛子.
对于bojinyu(沙鱼) 的代码,我正在研究,感谢您的慷慨。
to fanchka(狼仔) :您的感觉非常正确,我实际上是得到了一套b/s系统,数据库结构和script代码都有,但是其逻辑层正如您所说,使用了dll,我现在想偷懒:),借鉴其数据库和script代码开发自己的系统,但是在怎么实现逻辑层上有困惑。能不能用别的办法代替dll,而不需要大的改动script呢?安全方面暂且放在一边。因为对开发dll确实是一窍不通。一定会给几位加分的。分数不够我就再开帖子:)
就如同调用集合中的函数一样,没什么太奇妙的. 如果,你想通过脚本
来替代dll的逻辑,没什么好的方法,查看接口的实现代码,再把他的思路转
成脚本代码. 呵呵,我说的都感到麻烦,你做的怕更要烦. 若是系统小,这样子
该是可以,若是系统大,那你可要和老板多蹭点时间.good luck.