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

 最近有朋友问我要数据库访问相关的代码,我整理时,发现一个由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();
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值