您的位置:首页 > 数据库

用OLE DB进行数据库访问的封装类

2006-09-03 17:39 155 查看
最近有朋友问我要数据库访问相关的代码,我整理时,发现一个由oledb封装的类,是以前翻译并整理的,今天公开给大家:

如何使用该类:

执行一个SQL语句并取得返回值

为了执行一个SQL语句,你可以简单的进行如下操作:事例话一个CSQLQuery对象,调用Connect函数,
然后调用ExecuteSQL执行。Connect函数可以有多种选择,你可以自己决定由谁来提供数据源
CSQLQuery query;
query.Connect(pSession);//外部提供会话
query.ExecuteSQL("SELECT MAX(UnitPrice) FROM Products");

返回值肯能简单的象1,2,3,你可以定义变量然后使用运算符>>读出数据
double dblUnitPrice = 0;
query >> dblUnitPrice;

注意: 如果使用运算符,你必须注意数据类型的匹配. 例如, SQL Server数据类型int要匹配到C++ 的long类型.

如果想统一把结果转化为字符串,你就可以简单使用运算符>而不用关心类型匹配

CString str; query > str.

你也可以使用重载运算符<<来添加一个SQL语句的参数

double dblMaxPrice = 2.8;
CSQLQuery query;
query.Connect(pDataSource);//外部提供数据源
query << "SELECT ProductName,UnitPrice FROM Products WHERE UnitPrice > "
<< dblMaxPrice;
query.ExecuteSQL();

执行带有参数的存储过程就可以简单的如下执行:

double dblPar1 = 2.8, dblPar2 = 1.8;
CSQLQuery query;
query.Connect(pDataSource,pSession);//外部提供数据源和会话
query << "EXECUTE sp_MyProcedure " << dblPar1 << " , " << dblPar2;
query.ExecuteSQL();

执行Update语句可以按如下方式执行:

CSQLQuery query;
query.Connect(pszServerName, pszLoginName, pszPassword, pszDatabaseName);//由内部提供会话和数据源
query << "UPDATE Orders SET ShipName = 'MyName' WHERE EmployeeID = 5";
query.ExecuteSQL();

一些简单的使用例子:
使用list box的例子
void PoulateListBox(CListBox& box,double dblMaxPrice)
{
box.ResetContent();
CSQLQuery query;
query.Connect(pSession);//外部提供会话
query << "SELECT ProductID,ProductName FROM Products WHERE UnitPrice > "
<< dblMaxPrice;
if(!query.ExecuteSQL())
return;
while(!query.eof())
{
LONG lProductID = 0; CString strProductName;
query >> lProductID >> strProductName;
int idx = box.AddString(strProductName);
box.SetItemData(idx,lProductID);
}
}
一个CListCtrl的例子
void CQueryView::ShowQuery(const CString strTableName)
{
// 清空列表
m_listCtrl.DeleteAllItems();
while(m_listCtrl.DeleteColumn(0)) {}

CSQLQuery query;
query.Connect(pSession);//外部提供会话
query << " SELECT TOP 100 * FROM " << strTableName;
if(!query.ExecuteSQL())
return;

//显示返回表的列名
int cols = query.GetColumnsCount();
for( int nCol = 0; nCol < cols; nCol++)
{
CString strColName = query.GetColumnName(nCol);
m_listCtrl.InsertColumn(nCol,strColName,LVCFMT_LEFT,80);
}

//显示返回表
int nItem = 0;
while(!query.eof())
{
CString str; query > str;
m_listCtrl.InsertItem(nItem,str);
for( int nSubItem = 1; nSubItem < cols; nSubItem++)
{
CString str; query > str;
m_listCtrl.SetItemText(nItem,nSubItem,str);
}
nItem++;
}
}
不容易吗?

源代码如下:

////////////////////////////////////////////////////
//文件名称:SQLQuery.h
#if !defined(AFX_SQLQUERY_H__8DC91E9B_037C_11D3_8591_00C0DF240228__INCLUDED_)
#define AFX_SQLQUERY_H__8DC91E9B_037C_11D3_8591_00C0DF240228__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afxtempl.h>

#ifndef __AFXDB_H__
#include <afxdb.h> // for ...
#endif

//用于存储返回结果的类,重载了运算符便于使用
class CQueryObject : public CObject
{
DECLARE_DYNAMIC(CQueryObject)
public:
CQueryObject();
CQueryObject(const COleVariant& value);
virtual ~CQueryObject();
//删除自己
void RemoveAndDestroy();
//重载运算符
CQueryObject& operator>>(BYTE &value);
CQueryObject& operator>>(short &);
CQueryObject& operator>>(int &);
CQueryObject& operator>>(long &);
CQueryObject& operator>>(float &);
CQueryObject& operator>>(double &);
CQueryObject& operator>>(CY &value);
CQueryObject& operator>>(COleCurrency &value);
CQueryObject& operator>>(CTime &value);
CQueryObject& operator>>(COleDateTime &value);
CQueryObject& operator>>(CString &value);
CQueryObject& operator>(CString &value);
//唯一的成员变量,存放返回值
COleVariant m_value;
};

//用于存储返回结果的列表类,重载了运算符便于使用
class CQueryObjectList : public CTypedPtrList<CObList,CQueryObject*>
{
public:
CQueryObjectList();
virtual ~CQueryObjectList();
//删除自己
void RemoveAndDestroy();
//是否到末尾了
bool eof();
//取得列表开始位置
void InitPosition();
//重载运算符
CQueryObjectList& operator>>(BYTE &value);
CQueryObjectList& operator>>(short &);
CQueryObjectList& operator>>(CY &value);
CQueryObjectList& operator>>(COleCurrency &value);
CQueryObjectList& operator>>(int &);
CQueryObjectList& operator>>(long &);
CQueryObjectList& operator>>(float &);
CQueryObjectList& operator>>(double &);
CQueryObjectList& operator>>(TIMESTAMP_STRUCT &value);
CQueryObjectList& operator>>(CTime &value);
CQueryObjectList& operator>>(COleDateTime &value);
CQueryObjectList& operator>>(CString &value);
CQueryObjectList& operator>(CString &value);

protected:
//只是当前列表位置
POSITION m_pos;
};

inline
bool CQueryObjectList::eof()
{
return m_pos == NULL;
}

struct MYBIND
{//返回结果绑定结构,微软推荐
MYBIND()
{
memset(this, 0, sizeof(*this));
}

TCHAR szValue[40];//值
DWORD dwStatus;//类型
};

//返回错误绑定结构
struct MYERRORINFO
{
BSTR bstrSource;
BSTR bstrDescription;
DWORD dwHelpContext;
GUID guid;
BSTR bstrHelpFile;
};
//目前没有用到,用于多记录集的使用
class CWhyResults
{
public:
bool UseMultipleResults() { return m_bMultiple; }
IMultipleResults** GetMultiplePtrAddress() { return m_bMultiple? &m_spMultipleResults.p : NULL; }
IMultipleResults* GetMultiplePtr() { return m_bMultiple? m_spMultipleResults : NULL; }

CComPtr<IMultipleResults> m_spMultipleResults;

bool m_bMultiple;
};
//命令类
class CQueryCommand : public CCommand<CDynamicAccessor, CRowset, CWhyResults>
{
public:
CQueryCommand(bool bMultiple)
{
m_bMultiple = bMultiple;
}
};
//目前没有用到
class CMultipleQuery : public CQueryCommand
{
public:
CMultipleQuery():CQueryCommand(true){}
};
//目前使用的命令类,
class CSingleQuery : public CQueryCommand
{
public:
CSingleQuery():CQueryCommand(false){}
};
//用于执行SQL语句的类
class CSQLQuery : public CObject
{
DECLARE_DYNAMIC(CSQLQuery)
public:
CSQLQuery();
virtual ~CSQLQuery();

//取得错误信息
CString GetLastError();
//取得当前应用的会话指针,特别强调,如果m_bMySession= true说明这个会话会在本类关闭是失效
ATL::CSession* GetSession() const;
//取得当前应用的数据源指针,特别强调,如果m_bMyDataSource= true说明这个数据源会在本类关闭是失效
ATL::CDataSource* GetDataSource() const;

//取得返回数据个数
int GetDataCount();
//取得返回数据列表
CQueryObjectList& GetDataList();

//取得返回表的列数
UINT GetColumnsCount();
//取得返回表列名的数组
void GetColumns(CStringArray& dest);
//取得返回表的第nIndex列的列名
const CString GetColumnName(int nIndex);

//用于事务处理
HRESULT BeginTrans();
HRESULT Abort(BOID* pboidReason = NULL, BOOL bRetaining = FALSE, BOOL bAsync = FALSE) const;
HRESULT Commit(BOOL bRetaining = FALSE, DWORD grfTC = XACTTC_SYNC, DWORD grfRM = 0) const;

//如果只想取得某几列的值,可以在调用Empty函数后使用该函数添加想要查看的列的名称,如果不调用,默认取所有的列
void AddColumns(LPCSTR lpszCol);
//清空单取某几列的数组
void ClearColumns();

//是否到了末尾
bool eof();
//清空一些SQL语句等,在调用新的ExecuteSQL()前一定要执行
void Empty();
//某一个列名是否存在
bool IsExistColumn(LPCSTR lpszCol);
//清出最后一个SQL语句中逗号以后的部分
void RemoveLastComma();

//执行SQL语句
bool ExecuteSQL();
//执行SQL语句
bool ExecuteSQL(LPCSTR szSQL);

//从返回列表中取得列表中一个值
CQueryObject* Get();

//重载运算符
CSQLQuery& operator>>(BYTE &value);
CSQLQuery& operator>>(short &);
CSQLQuery& operator>>(CY &value);
CSQLQuery& operator>>(COleCurrency &value);
CSQLQuery& operator>>(int &);
CSQLQuery& operator>>(long &);
CSQLQuery& operator>>(float &);
CSQLQuery& operator>>(double &);
CSQLQuery& operator>>(CTime &value);
CSQLQuery& operator>>(COleDateTime &value);
CSQLQuery& operator>>(CString &value);
CSQLQuery& operator>(CString &value);

const CSQLQuery& operator =(const LPCSTR& right);
const CSQLQuery& operator +=(const LPCSTR& right);

CSQLQuery& operator<<(const long value);
CSQLQuery& operator<<(const double value);
CSQLQuery& operator<<(const BYTE value);
CSQLQuery& operator<<(const short value);
CSQLQuery& operator<<(const int value);
CSQLQuery& operator<<(const float value);
CSQLQuery& operator<<(LPCSTR value);
CSQLQuery& operator<<(const CTime &value);

protected:
//重置一些数据
void ReSet();
//删除命令类,执行SQL语句前执行
void DeleteCommand();
//如果允许显示错误信息,则弹出对话框显示错误内容

void ShowError(LPCSTR error);
//查找数据库操作失败错误信息并调用ShowError函数显示错误
void ShowDBError(IUnknown* pUnk, const IID& iid );
//检查是否有错误,如果有调用ShowError函数显示错误
bool CheckDBError(IUnknown* pUnk, const IID& iid );

//初始化会话,用于只提供数据源的连接,内部实现一个会话。
bool InitSession();
//把CDynamicAccessor的第nCol列的值转化为COleVariant类型值
COleVariant ToVariant(CDynamicAccessor*,int nCol);

protected:
//是否连接,即是否调用了Connect函数进行初始化
bool m_bConnected;

//存放数据源的指针
ATL::CDataSource* m_pDataSource;
//当前操作的数据库名称
CString m_strDatabase;
//存放会话的指针
ATL::CSession* m_pSession;
//命令指针
CQueryCommand* m_pCommand;

//如果想只取几列的值,则将想取的列的名称放到该成员中
CStringArray m_columns;

//返回结果列表
CQueryObjectList m_object_list;

//最后的错误信息
CString m_strError;

//是否内部创建了会话
bool m_bMySession;
//是否内部创建了数据源
bool m_bMyDataSource;

public:
//将要执行SQL语句
CString m_strQuery;
//最后产生的错误信息
bool m_bShowError;
public:
//add by stavck at 20040415
//取得记录数
int GetItemCount();
//add by stavck at 20031116
//为了方便使用,提供的一个数据连接 的函数,通过该函数进行数据源和会话的连接
bool ConnectSrv(ATL::CDataSource *pDataSource, ATL::CSession * pSession, LPCSTR pszServerName, LPCSTR pszLoginName, LPCSTR pszPassword, LPCSTR pszDatabase);

//关闭数据连接,如果想继续使用必须调用Connect函数进行新的连接
void Close();
//判断是否已经连接了
bool IsConnected(){return m_bConnected;}

//连接函数,可以有多种连接方法,可以是外部提供数据源,会话,也可以由内部提供
bool Connect(ATL::CDataSource* pDataSource,bool bShowError = true);
bool Connect(ATL::CDataSource* pDataSource,ATL::CSession* pSession,bool bShowError = true);
bool Connect(ATL::CSession* pSession,bool bShowError = true);
bool Connect(LPCSTR pszServerName, LPCSTR pszLoginName, LPCSTR pszPassword, LPCSTR pszDatabase = NULL, bool bShowError = true);
};

inline
HRESULT CSQLQuery::BeginTrans()
{
ASSERT(m_pSession);
if(m_pSession)
return m_pSession->StartTransaction();
else return S_FALSE;
}
inline
HRESULT CSQLQuery::Abort(BOID* pboidReason, BOOL bRetaining, BOOL bAsync) const
{
ASSERT(m_pSession);
if(m_pSession)
return m_pSession->Abort(pboidReason,bRetaining,bAsync);
else return S_FALSE;
}
inline
HRESULT CSQLQuery::Commit(BOOL bRetaining, DWORD grfTC, DWORD grfRM) const
{
ASSERT(m_pSession);
if(m_pSession)
return m_pSession->Commit(bRetaining,grfTC,grfRM);
else return S_FALSE;
}

inline
CQueryObjectList& CSQLQuery::GetDataList()
{ m_object_list.InitPosition();return m_object_list; }

inline
CString CSQLQuery::GetLastError()
{ return m_strError;}

inline
ATL::CSession* CSQLQuery::GetSession() const
{ return m_pSession;}

inline
ATL::CDataSource*CSQLQuery::GetDataSource() const
{ return m_pDataSource;}

inline
int CSQLQuery::GetDataCount()
{ return m_object_list.GetCount();}

inline
const CSQLQuery& CSQLQuery::operator =(const LPCSTR& right)
{
m_strQuery = right;
return *this;
}
inline
const CSQLQuery& CSQLQuery::operator +=(const LPCSTR& right)
{
m_strQuery += right;
return *this;
}
inline
CSQLQuery& CSQLQuery::operator<<(const long value)
{
CString str; str.Format("%d",value);
m_strQuery += str;
return *this;
}
inline
CSQLQuery& CSQLQuery::operator<<(const double value)
{
CString str; str.Format("%f",value);
m_strQuery += str;
return *this;
}
inline
CSQLQuery& CSQLQuery::operator<<(const BYTE value)
{
return *this << (long) value;
}
inline
CSQLQuery& CSQLQuery::operator<<(const short value)
{
return *this << (long) value;
}
inline
CSQLQuery& CSQLQuery::operator<<(const int value)
{
return *this << (long) value;
}
inline
CSQLQuery& CSQLQuery::operator<<(const float value)
{
return *this << (double) value;
}
inline
CSQLQuery& CSQLQuery::operator<<(LPCSTR value)
{
m_strQuery += value;
return *this;
}
inline
CSQLQuery& CSQLQuery::operator<<(const CTime &value)
{
m_strQuery += value.Format("'%m/%d/%Y %H:%M:%S'");
return *this;
}

inline
bool CSQLQuery::eof()
{
return m_object_list.IsEmpty()== TRUE;
}
inline CSQLQuery& __cdecl ccc(CSQLQuery& query) { return query << " , "; }

#endif // !defined(AFX_SQLQUERY_H__8DC91E9B_037C_11D3_8591_00C0DF240228__INCLUDED_)

//文件名称:SQLQuery.cpp

#include "stdafx.h"
#include "SQLQuery.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define pACCESSOR ((CDynamicAccessor*)m_pCommand)

//////////////////////////////////////////////////////////////////////
// CQueryObject

IMPLEMENT_DYNAMIC(CQueryObject,CObject);

CQueryObject::CQueryObject()
{
m_value.vt = VT_EMPTY;
}
CQueryObject::CQueryObject(const COleVariant& value)
{
m_value = value;
}

CQueryObject::~CQueryObject()
{
HRESULT hr = ::VariantClear(&m_value);
if (FAILED(hr))
{
ASSERT(0);
}
}
void CQueryObject::RemoveAndDestroy()
{
HRESULT hr = ::VariantClear(&m_value);
if (FAILED(hr))
{
ASSERT(0);
}
delete this;
}

CQueryObject& CQueryObject::operator>>(BYTE &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value = NULL;
}
else
{
ASSERT(m_value.vt == VT_I1 || m_value.vt == VT_UI1);
value = m_value.intVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(short &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value = NULL;
}
else
{
ASSERT(m_value.vt == VT_I2);
value = m_value.iVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(COleCurrency &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value.SetStatus(COleCurrency::CurrencyStatus::invalid);
}
else
{
ASSERT(m_value.vt == VT_CY);
value = m_value;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(CY &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value.Lo = NULL;
value.Hi = NULL;
}
else
{
ASSERT(m_value.vt == VT_CY);
value = m_value.cyVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(int &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value = NULL;
}
else
{
ASSERT(m_value.vt == VT_I4);
value = m_value.iVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(long &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value = NULL;
}
else
{
ASSERT(m_value.vt == VT_I4);
value = m_value.lVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(float &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value = NULL;
}
else
{
ASSERT(m_value.vt == VT_R4);
value = m_value.fltVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(double &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value = NULL;
}
else
{
ASSERT(m_value.vt == VT_R8);
value = m_value.dblVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(COleDateTime &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
//value = NULL;
}
else
{
ASSERT(m_value.vt == VT_DATE);
value = m_value.date;
}
return *this;
}

CQueryObject& CQueryObject::operator>>(CTime &value)
{
COleDateTime date;
*this >> date;
CTime time( date.GetYear(),date.GetMonth(),date.GetDay(),
date.GetHour(),date.GetMinute(),date.GetSecond());
value = time;
return *this;
}
CQueryObject& CQueryObject::operator>>(CString &value)
{
if( m_value.vt == VT_EMPTY || m_value.vt == VT_NULL)
{
value.Empty();
}
else
{
ASSERT(m_value.vt == VT_BSTR);
value = m_value.bstrVal;
}
return *this;
}

CQueryObject& CQueryObject::operator>(CString &value)
{
COleDateTime date;
switch(m_value.vt)
{
default:
ASSERT(0);
break;
case VT_CY:
{
COleCurrency cur(m_value.cyVal);
value = cur.Format();
}
break;
case VT_BOOL:
value.Format("%d",m_value.boolVal);
break;
case VT_DATE:
date = m_value;
value = date.Format("%d %b.%Y");
break;
case VT_EMPTY:
case VT_NULL:
value.Empty();
break;
case VT_I2:
case VT_I4:
value.Format("%d",m_value.lVal);
break;
case VT_R4:
value.Format("%.2f",m_value.fltVal);
break;
case VT_R8:
value.Format("%.2f",m_value.dblVal);
break;
case VT_BSTR:
*this >> value;
break;
}
return *this;
}

//////////////////////////////////////////////////////////////////////
// CQueryObjectList

CQueryObjectList::CQueryObjectList():
m_pos(NULL)
{
}

CQueryObjectList::~CQueryObjectList()
{
RemoveAndDestroy();
}

void CQueryObjectList::RemoveAndDestroy()
{
POSITION pos = GetHeadPosition();
while(pos != NULL)
{
GetNext(pos)->RemoveAndDestroy();
}
RemoveAll();
}

void CQueryObjectList::InitPosition()
{
m_pos = GetHeadPosition();
}

CQueryObjectList& CQueryObjectList::operator>>(BYTE &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(short &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(CY &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(COleCurrency &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}

CQueryObjectList& CQueryObjectList::operator>>(int &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(long &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(float &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(double &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(CTime &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(COleDateTime &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>>(CString &value)
{
if(m_pos)
*GetNext(m_pos)>> value;
return *this;
}
CQueryObjectList& CQueryObjectList::operator>(CString &value)
{
if(m_pos)
*GetNext(m_pos)> value;
return *this;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CSQLQuery,CObject);
CSQLQuery::CSQLQuery()
{
m_pDataSource = NULL;
m_bShowError = false;
m_pSession = NULL;
m_pCommand = NULL;
m_bMyDataSource = false;
m_bMySession = false;
m_bConnected = false;
}

CSQLQuery::~CSQLQuery()
{
Close();
}

void CSQLQuery::ShowError(LPCSTR error)
{
m_strError = error;
if(m_bShowError)
MessageBox(NULL,error,_T("提示"),MB_ICONERROR | MB_OK);
}

void CSQLQuery::ShowDBError(IUnknown* pUnk, const IID& iid )
{
CString strError;
CDBErrorInfo errInfo;
ULONG ulRecords = 0;
HRESULT hr = errInfo.GetErrorRecords(pUnk,iid, &ulRecords);
if (FAILED(hr) || hr == S_FALSE || ulRecords == 0)
{
ShowError(_T("没有指定的数据源,无法找到错误信息!"));
return ;
}
else
{
LCID lcid = GetUserDefaultLCID();
for (ULONG l=0; l<ulRecords; l++)
{
// Get the error information from the source
struct MYERRORINFO* pInfo = new MYERRORINFO;
hr = errInfo.GetAllErrorInfo(l, lcid, &pInfo->bstrDescription,
&pInfo->bstrSource, &pInfo->guid, &pInfo->dwHelpContext,
&pInfo->bstrHelpFile);
if (FAILED(hr))
{
delete pInfo;
continue;
}

strError += CString(pInfo->bstrDescription) + "/n";
delete pInfo;
}
}

ShowError(_T(strError));
}

bool CSQLQuery::CheckDBError(IUnknown* pUnk, const IID& iid )
{
CString strError;
CDBErrorInfo errInfo;
ULONG ulRecords = 0;
HRESULT hr = errInfo.GetErrorRecords(pUnk,iid, &ulRecords);
if (FAILED(hr) || hr == S_FALSE || ulRecords == 0)
{
// ShowError(_T("NOSPECIFIED_SOURCE"));
return false;
}
else
{
LCID lcid = GetUserDefaultLCID();
for (ULONG l=0; l<ulRecords; l++)
{
// Get the error information from the source
struct MYERRORINFO* pInfo = new MYERRORINFO;
hr = errInfo.GetAllErrorInfo(l, lcid, &pInfo->bstrDescription,
&pInfo->bstrSource, &pInfo->guid, &pInfo->dwHelpContext,
&pInfo->bstrHelpFile);
if (FAILED(hr))
{
delete pInfo;
continue;
}

strError += CString(pInfo->bstrDescription) + "/n";
delete pInfo;
}
}

if(!strError.IsEmpty())
{
ShowError(_T(strError));
return true;
}
return false;
}

void CSQLQuery::Empty()
{
m_strError.Empty();
m_strQuery.Empty();
m_object_list.RemoveAndDestroy();
DeleteCommand();
ClearColumns();
}

bool CSQLQuery::InitSession()
{
ASSERT(m_pSession == NULL);

if(m_pSession == NULL)
m_pSession = new CSession;

if (m_pSession->m_spOpenRowset != NULL)
m_pSession->m_spOpenRowset.Release();

USES_CONVERSION;

if (m_pSession->Open(*GetDataSource()) != S_OK)
{
ShowError(_T("无法在此数据源的基础上创建会话!"));
return false;
}

return true;
}

COleVariant CSQLQuery::ToVariant(CDynamicAccessor* pDynamicAccessor,int nCol)
{
ASSERT(pDynamicAccessor != NULL);
COleVariant vt;
DBSTATUS dbStatus;
DBTYPE dbType;

pDynamicAccessor->GetStatus(nCol, &dbStatus);
if(dbStatus == DBSTATUS_S_ISNULL)
return vt; // just return a blank variant

if(!pDynamicAccessor->GetColumnType(nCol, &dbType))
return vt;
switch (dbType)
{
case DBTYPE_VARIANT:
vt = COleVariant((LPCVARIANT)pDynamicAccessor->GetValue(nCol));
break;
case DBTYPE_STR:
vt = COleVariant(CString((LPCSTR)pDynamicAccessor->GetValue(nCol)), VT_BSTR);
break;
case DBTYPE_WSTR:
case DBTYPE_BSTR:
vt = COleVariant(CString((LPCWSTR)pDynamicAccessor->GetValue(nCol)), VT_BSTR);
break;
case DBTYPE_I1:
case DBTYPE_UI1:
vt = COleVariant(*((BYTE*)pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_I2:
case DBTYPE_UI2:
vt = COleVariant(*((short*)pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_I4:
case DBTYPE_UI4:
vt = COleVariant(*((long*)pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_R4:
vt = COleVariant(*((float*)pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_R8:
vt = COleVariant(*((double*)pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_BOOL:
vt = COleVariant((short)*(BOOL*)pDynamicAccessor->GetValue(nCol), VT_BOOL);
break;
case DBTYPE_DATE:
{
COleDateTime dt(*((DATE*)pDynamicAccessor->GetValue(nCol)));
vt = COleVariant(dt);
}
break;
case DBTYPE_CY:
{
COleCurrency cy(*((CURRENCY*)pDynamicAccessor->GetValue(nCol)));
vt = COleVariant(cy);
}
break;
case DBTYPE_NUMERIC:
{
DB_NUMERIC num;

if(pDynamicAccessor->GetValue(nCol, &num))
{
double dbl;

dbl = (double)*((__int64*)num.val);
while(num.scale-- > 0)
dbl /= 10;
if(num.sign == 0)
dbl = -dbl;
vt = COleVariant(dbl);
}
}
break;
case DBTYPE_DBDATE:
{
DBDATE dbDate;

if(pDynamicAccessor->GetValue(nCol, &dbDate))
{
COleDateTime dt;

dt.SetDate(dbDate.year, dbDate.month, dbDate.day);
vt = COleVariant(dt);
}
}
break;
case DBTYPE_DBTIME:
{
DBTIME dbTime;

if(pDynamicAccessor->GetValue(nCol, &dbTime))
{
COleDateTime dt;

dt.SetTime(dbTime.hour, dbTime.minute, dbTime.second);
vt = COleVariant(dt);
}
}
break;
case DBTYPE_DBTIMESTAMP:
{
DBTIMESTAMP dbTimeStamp;

if(pDynamicAccessor->GetValue(nCol, &dbTimeStamp))
{
vt = COleVariant(COleDateTime(dbTimeStamp.year, dbTimeStamp.month, dbTimeStamp.day,
dbTimeStamp.hour, dbTimeStamp.minute, dbTimeStamp.second));
}
}
break;
case DBTYPE_NULL:
case DBTYPE_EMPTY:
break;
default:
TRACE2("不支持的数据类型(%d)在第%d列/n", dbType, nCol);
ASSERT(0);
break;
}
return vt;
}

CQueryObject* CSQLQuery::Get()
{
return m_object_list.IsEmpty() ? NULL : m_object_list.RemoveHead();
}

CSQLQuery& CSQLQuery::operator>>(BYTE &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}

CSQLQuery& CSQLQuery::operator>>(short &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}
CSQLQuery& CSQLQuery::operator>>(CY &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}
CSQLQuery& CSQLQuery::operator>>(COleCurrency &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}

CSQLQuery& CSQLQuery::operator>>(int &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}

CSQLQuery& CSQLQuery::operator>>(long &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}

CSQLQuery& CSQLQuery::operator>>(float &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}
CSQLQuery& CSQLQuery::operator>>(double &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}
CSQLQuery& CSQLQuery::operator>>(CTime &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}
CSQLQuery& CSQLQuery::operator>>(COleDateTime &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}
CSQLQuery& CSQLQuery::operator>>(CString &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj >> value;
delete pObj;
}
return *this;
}

CSQLQuery& CSQLQuery::operator>(CString &value)
{
CQueryObject* pObj = Get();
ASSERT(pObj);
if(pObj)
{
*pObj > value;
delete pObj;
}
return *this;
}

void CSQLQuery::AddColumns(LPCSTR lpszCol)
{
m_columns.Add(lpszCol);
}

void CSQLQuery::ClearColumns()
{
m_columns.RemoveAll();
}

UINT CSQLQuery::GetColumnsCount()
{
ASSERT(m_pCommand);
if(!m_pCommand)
return 0;

UINT cnt = pACCESSOR->GetColumnCount();
return cnt;
}

const CString CSQLQuery::GetColumnName(int nIndex)
{
ULONG nCol = nIndex + 1;
CString strName = pACCESSOR->GetColumnName(nCol);
return strName;
}

void CSQLQuery::GetColumns(CStringArray& dest)
{
UINT cnt = GetColumnsCount();
ULONG nCol = 1;
while(cnt--)
{
CString str = pACCESSOR->GetColumnName(nCol++);
dest.Add(str);
}
}

bool CSQLQuery::IsExistColumn(LPCSTR lpszCol)
{
UINT cnt = GetColumnsCount();
if(cnt == 0)
return false;
ULONG nCol = 1;
while(cnt--)
{
CString str = pACCESSOR->GetColumnName(nCol++);
if(str == lpszCol)
return true;
}

return false;
}

void CSQLQuery::RemoveLastComma()
{
int idx = m_strQuery.ReverseFind(',');
if(idx != -1)
m_strQuery.SetAt(idx,' ');
}

bool CSQLQuery::ExecuteSQL(LPCSTR szSQL)
{
m_strQuery = szSQL;
return ExecuteSQL();
}

bool CSQLQuery::ExecuteSQL()
{
HRESULT hr;
if(m_strQuery.IsEmpty())
{
ShowError("SQL查询语句是空的!");
return false;
}
ReSet();

m_pCommand = new CSingleQuery;

CDBPropSet propset(DBPROPSET_ROWSET);

bool bBind = true;
hr = m_pCommand->Open(*GetSession(), m_strQuery, &propset, NULL, DBGUID_DEFAULT, false);
if (hr != S_OK)
{
ShowDBError(m_pCommand->m_spCommand, IID_ICommand);
return false;
}

if(m_pCommand->GetInterface() != NULL)
{
hr = m_pCommand->Bind();
if (hr != S_OK)
{
ShowDBError(m_pCommand->m_spCommand, IID_ICommand);
return false;
}
}

// Display the data
if(m_pCommand->GetInterface() != NULL)
while(m_pCommand->MoveNext() == S_OK)
{
if(m_columns.GetSize() == 0)
{
for(ULONG nCol = 0; nCol < m_pCommand->GetColumnCount(); nCol++)
{
COleVariant vt = ToVariant(m_pCommand,nCol+1);
CQueryObject*pObj = new CQueryObject(vt);
m_object_list.AddTail(pObj);
vt.Clear();
}
}
else
{
for(int i = 0; i < m_columns.GetSize(); i++)
{
ULONG nCol = 0;
LPCSTR pColumnName = m_columns[i];
bool bOk = m_pCommand->GetInternalColumnNo((char*)pColumnName,&nCol);
ASSERT(bOk);
COleVariant vt = ToVariant(m_pCommand,nCol+1);
CQueryObject*pObj = new CQueryObject(vt);
m_object_list.AddTail(pObj);
vt.Clear();
}
}

}
return true;
}

void CSQLQuery::DeleteCommand()
{
if(m_pCommand)
{
delete m_pCommand;
}
m_pCommand = NULL;
}

//add by stavck at 20031116
void CSQLQuery::Close()
{
ReSet();
if(m_bMySession && m_pSession != NULL)
{
m_pSession->Close();
delete m_pSession;
}
if(m_bMyDataSource && m_pDataSource != NULL)
{
m_pDataSource->Close();
delete m_pDataSource;
}
m_pSession = NULL;
m_pDataSource = NULL;
m_bConnected = false;

}

bool CSQLQuery::ConnectSrv(ATL::CDataSource *pDataSource, ATL::CSession *pSession, LPCSTR pszServerName, LPCSTR pszLoginName, LPCSTR pszPassword, LPCSTR pszDatabase)
{
CString strServer(pszServerName);
CString strUser(pszLoginName);
CString strPassword(pszPassword);

if (pSession && pSession->m_spOpenRowset != NULL)
pSession->m_spOpenRowset.Release();

CDBPropSet dbinit(DBPROPSET_DBINIT);

dbinit.AddProperty(DBPROP_AUTH_USERID, strUser);
dbinit.AddProperty(DBPROP_AUTH_PASSWORD, strPassword);
dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false);
dbinit.AddProperty(DBPROP_INIT_DATASOURCE, strServer);
dbinit.AddProperty(DBPROP_INIT_LCID, (long)2052);
dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
dbinit.AddProperty(DBPROP_INIT_TIMEOUT, (long)60);
dbinit.AddProperty(DBPROP_INIT_PROVIDERSTRING, OLESTR(""));
dbinit.AddProperty(DBPROP_OUTPUTPARAMETERAVAILABILITY, DBPROPVAL_OA_ATROWRELEASE);
dbinit.AddProperty(DBPROP_MULTIPLESTORAGEOBJECTS, VARIANT_TRUE);
//支持多返回值
dbinit.AddProperty(DBPROP_MULTIPLERESULTS, DBPROPVAL_MR_SUPPORTED);
if(pszDatabase != NULL)
{
m_strDatabase = pszDatabase;
dbinit.AddProperty(DBPROP_INIT_CATALOG, m_strDatabase);
}
else
{
m_strDatabase.Empty();
}
dbinit.AddProperty(DBPROP_MULTIPLEPARAMSETS, VARIANT_TRUE);

if(FAILED(pDataSource->Open(_T("SQLOLEDB.1"), &dbinit)))
{
m_strError.Format(_T("不能连接到数据源:Server[%s] Database[%s] Login[%s]"), pszServerName, m_strDatabase, pszLoginName);
if(pDataSource!=NULL)
{
pDataSource->Close();
}
return false;
}
else
{
if (pSession && pSession->Open(*pDataSource) != S_OK)
{
m_strError = _T("无法在此数据源的基础上创建会话!");
pDataSource->Close();
return false;
}
}
return true;
}

void CSQLQuery::ReSet()
{
m_object_list.RemoveAndDestroy();
DeleteCommand();
ClearColumns();
}

bool CSQLQuery::Connect(ATL::CDataSource* pDataSource,bool bShowError)
{
if(IsConnected())
{
m_strError = _T("打开数据源前请先关闭数据源!");
return false;
}
m_bShowError = bShowError;
m_pDataSource = pDataSource;
m_bMySession = true;
m_bMyDataSource = false;
if(pDataSource)
{
InitSession();
CComVariant var;
if(SUCCEEDED(pDataSource->
GetProperty(DBPROPSET_DATASOURCE,DBPROP_CURRENTCATALOG, &var) &&
var.vt != VT_EMPTY && var.vt != VT_NULL))
{
USES_CONVERSION;
m_strDatabase = OLE2T(var.bstrVal);
}
else
{
ASSERT(0);
}
}
m_bConnected = true;
return true;
}

bool CSQLQuery::Connect(ATL::CDataSource* pDataSource,ATL::CSession* pSession,bool bShowError)
{
if(IsConnected())
{
m_strError = _T("打开数据源前请先关闭数据源!");
return false;
}
m_pDataSource = pDataSource;
m_bShowError = bShowError;
m_pSession = pSession;
m_pCommand = NULL;
m_bMyDataSource = false;
m_bMySession = false;
if(pDataSource)
{
CComVariant var;
if(SUCCEEDED(pDataSource->
GetProperty(DBPROPSET_DATASOURCE,DBPROP_CURRENTCATALOG, &var) &&
var.vt != VT_EMPTY && var.vt != VT_NULL))
{
USES_CONVERSION;
m_strDatabase = OLE2T(var.bstrVal);
}
else
{
ASSERT(0);
}
}
m_bConnected = true;
return true;
}

bool CSQLQuery::Connect(CSession* pSession,bool bShowError)
{
if(IsConnected())
{
m_strError = _T("打开数据源前请先关闭数据源!");
return false;
}
m_pDataSource = NULL;
m_bShowError = bShowError;
m_pSession = pSession;
m_pCommand = NULL;
m_bMySession = false;
m_bMyDataSource = false;
m_bConnected = true;
return true;
}

bool CSQLQuery::Connect(LPCSTR pszServerName, LPCSTR pszLoginName, LPCSTR pszPassword, LPCSTR pszDatabase, bool bShowError)
{
if(IsConnected())
{
m_strError = _T("打开数据源前请先关闭数据源!");
return false;
}
m_pDataSource = new ATL::CDataSource;
m_pSession = new ATL::CSession;
m_bShowError = bShowError;
m_pCommand = NULL;
m_bMySession = true;
m_bMyDataSource = true;
if(pszDatabase != NULL)
{
m_strDatabase = pszDatabase;
}
if(!ConnectSrv(m_pDataSource, m_pSession, pszServerName, pszLoginName, pszPassword, m_strDatabase))
{
Close();
m_bConnected = false;
return false;
}

m_bConnected = true;
return true;
}

int CSQLQuery::GetItemCount()
{
return m_object_list.GetCount()/GetColumnsCount();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: