由于工作需要,查找了很多关于数据库连接池的实现代码.但是发现很多都是JAVA 版本的.我试着改了一下,
代码如下:
/******************************************************************
*
* ADO 对象的简单封装
*
*******************************************************************/
#ifndef _DATA_BASE_H_
#define _DATA_BASE_H_
#define CATCHERROR(ptr,a) catch(_com_error &e)/
{/
ErrorHandler(e,m_ErrStr);/
ptr=NULL;/
return a;/
}
#define CATCHERRGET catch(_com_error &e)/
{/
ErrorHandler(e,m_ErrStr);/
sprintf(m_ErrStr,"%s/n**For Field Name:%s",m_ErrStr,FieldName);/
return 0;/
}
#import "c:/Program Files/Common Files/System/ADO/msado25.tlb" /
rename("EOF", "EndOfFile")
typedef _RecordsetPtr RecPtr;
typedef _ConnectionPtr CnnPtr;
class Database;
class Table;
class Database
{
public:
BOOL RollBack();
BOOL CommitTrans();
BOOL BeginTrans();
void Close();
CnnPtr m_Cnn;
char m_ErrStr[500];
Database();
bool Open(char* UserName, char* Pwd,char* CnnStr);
bool OpenTbl(int Mode, char* CmdStr, Table& Tbl);
bool Execute(char* CmdStr, long * lRecordAffected, long Option);
bool Execute(char* CmdStr, Table& Tbl);
void GetErrorErrStr(char* ErrStr);
};
class Table{
public:
int GetBinaryLen(char * FieldName);
bool GetBinary(char * FieldName, BYTE * pValue);
BOOL SetPageSize(int size);
bool Move(int index);
int GetRecordCount();
bool Get(char * FieldNam, DWORD & value);
bool Get(char * FieldName, BYTE * pValue);
bool Get(char * FieldName, short & value);
bool Get(char * FieldName, BYTE &value);
RecPtr m_Rec;
char m_ErrStr[500];
int m_pageSize;
Table();
void GetErrorErrStr(char* ErrStr);
int ISEOF();
HRESULT MoveNext();
HRESULT MovePrevious();
bool MoveFirst();
HRESULT MoveLast();
/*
int AddNew();
int Update();
int Add(char* FieldName, char* FieldValue);
int Add(char* FieldName,int FieldValue);
int Add(char* FieldName,float FieldValue);
int Add(char* FieldName,double FieldValue);
int Add(char* FieldName,long FieldValue);
*/
bool Get(char* FieldName, char* FieldValue);
bool Get(char* FieldName,int& FieldValue);
bool Get(char* FieldName,float& FieldValue);
bool Get(char* FieldName,double& FieldValue);
bool Get(char* FieldName,double& FieldValue,int Scale);
bool Get(char* FieldName,long& FieldValue);
};
#endif _DATA_BASE_H_
//database.cpp
#include <stdio.h>
#include <iostream.h>
#include <comdef.h>
#include <conio.h>
#include <atlbase.h>
#include "stdafx.h"
#include "Database.h"
#include "htrdserver.h"
_variant_t vtMissing1(DISP_E_PARAMNOTFOUND, VT_ERROR);
static void ErrorHandler(_com_error &e, char* ErrStr)
{
sprintf(ErrStr,"Error:/n");
sprintf(ErrStr,"%sCode = %08lx/n",ErrStr ,e.Error());
sprintf(ErrStr,"%sCode meaning = %s/n", ErrStr, (char*) e.ErrorMessage());
sprintf(ErrStr,"%sSource = %s/n", ErrStr, (char*) e.Source());
sprintf(ErrStr,"%sDescription = %s",ErrStr, (char*) e.Description());
}
Database::Database()
{
m_Cnn=NULL;
sprintf(m_ErrStr,"NULL POINTER");
}
void Database::GetErrorErrStr(char* ErrStr)
{
sprintf(ErrStr,"%s",m_ErrStr);
}
void Table::GetErrorErrStr(char* ErrStr)
{
sprintf(ErrStr,"%s",m_ErrStr);
}
bool Database::Open(char* UserName, char* Pwd,char* CnnStr)
{
//cnn->Open(strCnn,"sa","sa",NULL);
try
{
HRESULT hr;
hr = m_Cnn.CreateInstance( __uuidof( Connection ) );
m_Cnn->Open(CnnStr, UserName, Pwd, NULL);
}
CATCHERROR(m_Cnn,0)
sprintf(m_ErrStr,"Success");
return 1;
}
bool Database::OpenTbl(int Mode, char* CmdStr, Table &Tbl)
{
if(m_Cnn==NULL)
{
Tbl.m_Rec=NULL;
sprintf(m_ErrStr,"Invalid Connection");
return 0;
}
RecPtr t_Rec=NULL;
try
{
//t_Rec->putref_ActiveConnection(m_Cnn);
//vtMissing<<-->>_variant_t((IDispatch *) m_Cnn, true)
t_Rec.CreateInstance( __uuidof( Recordset ) );
t_Rec->Open(CmdStr,_variant_t((IDispatch *) m_Cnn, true),adOpenStatic,adLockOptimistic,Mode);
}
CATCHERROR(Tbl.m_Rec,0)
Tbl.m_Rec=t_Rec;
sprintf(m_ErrStr,"Success");
return 1;
}
bool Database::Execute(char* CmdStr, long * lRecordAffected, long Option)
{
VARIANT var;
var.vt = VT_I4;
try
{
m_Cnn->Execute(CmdStr,&var,Option);
*lRecordAffected = var.lVal;
}
catch(_com_error &e)
{
ErrorHandler(e,m_ErrStr);
CString str;
str.Format("数据库执行错误,消息:%s/r/n", m_ErrStr);
OUTPUT_MSG(str);
return 0;
}
sprintf(m_ErrStr,"Success");
return 1;
}
bool Database::Execute(char* CmdStr, Table& Tbl)
{
// TRACE(CmdStr);
int t = strlen(CmdStr);
RecPtr t_Rec=NULL;
try
{
t_Rec=m_Cnn->Execute(CmdStr,NULL,1);
}
catch(_com_error &e)
{
ErrorHandler(e,m_ErrStr);
CString str;
str.Format("数据库执行错误,消息:%s/r/n", m_ErrStr);
OUTPUT_MSG(str);
return 0;
}
sprintf(m_ErrStr,"Success");
Tbl.m_Rec=t_Rec;
sprintf(m_ErrStr,"Success");
return 1;
}
Table::Table()
{
m_Rec=NULL;
m_pageSize = -1;
}
int Table::ISEOF()
{
int rs;
if(m_Rec==NULL)
{
sprintf(m_ErrStr,"Invalid Record");
return -1;
}
try{
rs=m_Rec->adoEOF;
}
CATCHERROR(m_Rec,-2)
sprintf(m_ErrStr,"Success");
return rs;
}
bool Table::Get(char* FieldName, char* FieldValue)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
if (vtValue.vt == VT_NULL)
{
sprintf((char *)FieldValue , "");
return true;
}
VariantChangeType(&vtValue,&vtValue,0, VT_BYREF|VT_BSTR);
sprintf(FieldValue,"%s",(LPCSTR)((_bstr_t)vtValue.bstrVal));
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
bool Table::Get(char* FieldName,int& FieldValue)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
VariantChangeType(&vtValue,&vtValue,0, VT_I4);
FieldValue=vtValue.intVal;
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
bool Table::Get(char* FieldName,float& FieldValue)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
if (vtValue.vt == VT_NULL)
{
FieldValue = 0;
return true;
}
VariantChangeType(&vtValue,&vtValue,0, VT_R4);
FieldValue=vtValue.fltVal;
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
bool Table::Get(char* FieldName,double& FieldValue)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
if (vtValue.vt == VT_NULL)
{
FieldValue = 0;
return true;
}
VariantChangeType(&vtValue,&vtValue,0, VT_R8);
FieldValue = vtValue.dblVal;
//GetDec(vtValue,FieldValue,3);
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
HRESULT Table::MoveNext()
{
HRESULT hr;
try
{
hr=m_Rec->MoveNext();
}
catch(_com_error &e)
{
ErrorHandler(e,m_ErrStr);
//m_Rec=NULL;
return -2;
}
sprintf(m_ErrStr,"Success");
return hr;
}
HRESULT Table::MovePrevious()
{
HRESULT hr;
try
{
hr=m_Rec->MovePrevious();
}
catch(_com_error &e)
{
ErrorHandler(e,m_ErrStr);
//m_Rec=NULL;
return -2;
}
sprintf(m_ErrStr,"Success");
return hr;
}
bool Table::MoveFirst()
{
HRESULT hr;
try
{
hr=m_Rec->MoveFirst();
}
catch(_com_error &e)
{
ErrorHandler(e,m_ErrStr);
//m_Rec=NULL;
return false;
}
sprintf(m_ErrStr,"Success");
return true;
}
HRESULT Table::MoveLast()
{
HRESULT hr;
try
{
hr=m_Rec->MoveLast();
}
catch(_com_error &e)
{
ErrorHandler(e,m_ErrStr);
//m_Rec=NULL;
return -2;
}
sprintf(m_ErrStr,"Success");
return hr;
}
void Database::Close()
{
try
{
m_Cnn = NULL;
}
catch (_com_error e)
{
LPCTSTR lpsz = e.ErrorMessage();
}
}
bool Table::Get(char *FieldName, BYTE &value)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
if (vtValue.vt == VT_NULL)
{
value = 0;
return true;
}
VariantChangeType(&vtValue,&vtValue,0, VT_UI1);
value=vtValue.bVal;
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
bool Table::Get(char *FieldName, short &value)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
if (vtValue.vt == VT_NULL)
{
value = 0;
return true;
}
VariantChangeType(&vtValue,&vtValue,0, VT_I2);
value=vtValue.iVal;
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
bool Table::Get(char *FieldName, BYTE *pValue)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
if (vtValue.vt == VT_NULL)
{
sprintf((char *)pValue , "");
return true;
}
VariantChangeType(&vtValue,&vtValue,0, VT_BSTR);
sprintf((char *)pValue,"%s",(LPCSTR)((_bstr_t)vtValue.bstrVal));
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
bool Table::Get(char *FieldName, DWORD &value)
{
try
{
_variant_t vtValue;
vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue();
if (vtValue.vt == VT_NULL)
{
value = 0;
return true;
}
VariantChangeType(&vtValue,&vtValue,0, VT_I4);
value = vtValue.lVal;
}
CATCHERRGET
sprintf(m_ErrStr,"Success");
return 1;
}
int Table::GetRecordCount()
{
if (m_Rec == NULL)
return 0;
int ret = 0;
if (!ISEOF())
MoveFirst();
while(!ISEOF())
{
ret++;
MoveNext();
}
return ret;
}
bool Table::Move(int index)
{
if (index == 0)
return true;
try
{
m_Rec->Move(index);
}
catch (_com_error e)
{
LPCTSTR lpsz = e.ErrorMessage();
}
sprintf(m_ErrStr,"Success");
return 1;
}
BOOL Database::BeginTrans()
{
if (m_Cnn == NULL)
return FALSE;
try
{
m_Cnn->BeginTrans();
}
catch(_com_error e)
{
LPCTSTR lpsz = e.ErrorMessage();
return FALSE;
}
return TRUE;
}
BOOL Database::CommitTrans()
{
if (m_Cnn == NULL)
return FALSE;
try
{
m_Cnn->CommitTrans();
}
catch(_com_error e)
{
LPCTSTR lpsz = e.ErrorMessage();
return FALSE;
}
return TRUE;
}
BOOL Table::SetPageSize(int size)
{
if (m_Rec == NULL)
return FALSE;
if (GetRecordCount() < size)
return FALSE;
m_pageSize = size;
return TRUE;
}
BOOL Database::RollBack()
{
if (m_Cnn == NULL)
return FALSE;
try
{
m_Cnn->RollbackTrans();
}
catch(_com_error e)
{
LPCTSTR lpsz = e.ErrorMessage();
return FALSE;
}
return TRUE;
}
/*
* purpose: get the binary filed value from data base
* the memory of pValue must be allocated by the user.
* the length of pValue is known as before.
*/
bool Table::GetBinary(char *FieldName, BYTE *pValue)
{
HRESULT hr = -1;
try
{
_StreamPtr m_pStream;
hr = m_pStream.CreateInstance(__uuidof(Stream));
m_pStream->PutType(adTypeBinary);
_variant_t vtEmpty (DISP_E_PARAMNOTFOUND, VT_ERROR);
_bstr_t bstrEmpty(L"");
hr = m_pStream->Open(vtEmpty,adModeUnknown,adOpenStreamUnspecified,
bstrEmpty, bstrEmpty);
hr = m_pStream->Write(m_Rec->Fields->GetItem(FieldName)->Value);
m_pStream->Position = 0;
_variant_t var(m_pStream->Read(adReadAll));
LONG lDataLength = m_pStream->GetSize();
BYTE * pBuff= (BYTE *)GlobalAlloc(GMEM_FIXED, lDataLength);
if(var.vt == (VT_ARRAY | VT_UI1))
{
HRESULT hr = -1;
hr = SafeArrayAccessData(var.parray, (void **)&pBuff);
memcpy(pValue, pBuff, lDataLength);
GlobalFree((HGLOBAL)pBuff);
}
else
{
GlobalFree((HGLOBAL)pBuff);
return false;
}
m_pStream->Close();
}
catch ( _com_error e)
{
LPCTSTR lpsz = e.ErrorMessage();
if (hr == 0)
return true;
else
return false;
}
return true;
}
int Table::GetBinaryLen(char *FieldName)
{
int nRet = 0;
try
{
nRet = m_Rec->Fields->GetItem(FieldName)->ActualSize;
}
catch(_com_error e)
{
nRet = 0;
}
return nRet;
}
// ConnObject.h: interface for the CConnObject class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CONNOBJECT_H__2818382C_8737_44D0_B319_1032C614EFEE__INCLUDED_)
#define AFX_CONNOBJECT_H__2818382C_8737_44D0_B319_1032C614EFEE__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Database.h"
class CConnPool;
class CConnObject
{
public:
CConnObject(CConnPool * pool)
{
ASSERT(pool);
pPool = pool;
// conn = NULL;
m_bInUse = FALSE;
m_nLastEnd = 0;
m_nLastBegin = 0;
m_nUseCount = 0;
m_nTotalUseTime = 0;
}
~CConnObject();
// 用完本身不能关闭,交给连接池处理
public:
//释放连接对象给连接池
void Close();
Database conn;
BOOL m_bInUse;
int m_nLastEnd; //最后一次使用结束时间
int m_nLastBegin; //最后一次开始时间
int m_nUseCount; //使用次数
CConnPool * pPool;
int m_nTotalUseTime;
public:
//得到总得使用时间
int GetTotalUseTime()
{
return m_nTotalUseTime;
}
};
CConnObject::~CConnObject()
{
}
void CConnObject::Close()
{
m_nTotalUseTime += GetTickCount() - m_nLastBegin;
pPool->Close(this);
}
#endif //
// ConnPool.h: interface for the CConnPool class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CONNPOOL_H__FD09CC72_3241_4A82_912F_06F92BE1CD54__INCLUDED_)
#define AFX_CONNPOOL_H__FD09CC72_3241_4A82_912F_06F92BE1CD54__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <atlbase.h>
#include "ConnObject.h"
/***************************************
数据库连接池.
一个连接池对应于一个库
****************************************/
/*
*/
class CConnPool
{
public:
void OnTimer();
static void __stdcall TimerProc(HWND hWnd, UINT msg, UINT id, DWORD dwTime);
//得到一个连接
CConnObject * GetConnect();
//释放一个连接回连接池
void Close(CConnObject * pConn);
//销毁连接池
void Destroy();
//创建连接池 strConn: 连接串
BOOL Init(CString strConn);
CConnPool();
virtual ~CConnPool();
public:
UINT m_nTimer; //定时器
CSimpleArray<CConnObject *> m_listConn; //连接链表
UINT m_nTimeOut; //连接最大空闲时间
UINT m_ConnMax; //连接数量上限
UINT m_ConnMin; //连接数量下限
UINT m_nMaxCount; //连接最大使用次数
UINT m_nMaxUseTime; //最大使用时间
CString m_strConn; //连接串
HANDLE m_cs; //保证改变连接池状态时代码不终端
protected:
//创建一个新的连接
CConnObject * CreateNewConn();
};
#endif // !defined(AFX_CONNPOOL_H__FD09CC72_3241_4A82_912F_06F92BE1CD54__INCLUDED_)
// ConnPool.cpp: implementation of the CConnPool class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HTRDServer.h"
#include "ConnPool.h"
#include "const_def.h"
#include "MyEvent.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CConnPool::CConnPool()
{
m_ConnMin = CONN_MIN;
m_nTimeOut = CONN_TIMEOUT;
m_nMaxUseTime = CONN_MAX_USETIME;
m_nMaxCount = 500;
m_cs = CreateEvent(NULL, TRUE, TRUE, "da8b4c9d-e4ef-4c9a-a6d2-941ee98400d2");
}
CConnPool::~CConnPool()
{
Destroy();
}
BOOL CConnPool::Init(CString strConn)
{
m_ConnMax = theApp.m_sysSetting.m_nConnCount;
m_strConn = strConn;
for (UINT i = 0;i < m_ConnMax; i++)
{
CConnObject * pObj = CreateNewConn();
if (!pObj)
return FALSE;
m_listConn.Add(pObj);
}
return TRUE;
//启动连接池维护计时器
// m_nTimer = SetTimer(0, 0, CONNPOOL_TIMER, (TIMERPROC)TimerProc);
}
void CConnPool::Destroy()
{
for (int i = 0;i < m_listConn.GetSize(); i++)
{
m_listConn[i]->m_bInUse = FALSE;
m_listConn[i]->conn.Close();
// m_listConn[i]->conn->Release();
delete m_listConn[i];
}
m_listConn.RemoveAll();
KillTimer(NULL, m_nTimer);
}
/*
* 释放连接时需要保护数据一致性,所以使用 临界对象
*/
void CConnPool::Close(CConnObject *pConn)
{
//回收!
CMyEvent cs(m_cs);
for (int i = 0;i < m_listConn.GetSize(); i++)
{
if (m_listConn[i] == pConn)
{
m_listConn[i]->m_bInUse = FALSE;
m_listConn[i]->m_nUseCount++;
m_listConn[i]->m_nLastEnd = ::GetTickCount();
//判断使用次数是否过多,使用时间是否过多
//如果过度使用该连接,则重新创建
if (m_listConn[i]->m_nUseCount > (int)m_nMaxCount ||
m_listConn[i]->GetTotalUseTime() > CONN_MAX_USETIME)
{
OUTPUT_MSG("有数据库连接对象使用过多,需要重新连接/r/n");
m_listConn[i]->conn.Close();
if (!m_listConn[i]->conn.Open("", "", m_strConn.GetBuffer(0)))
{
AfxMessageBox("重新数据库连接对象出错!, 系统退出!");
ExitProcess(0);
}
m_listConn[i]->m_nLastBegin = 0;
m_listConn[i]->m_nLastEnd = 0;
m_listConn[i]->m_nTotalUseTime = 0;
m_listConn[i]->m_nUseCount = 0;
}
return;
}
}
#ifdef _DEBUG
AfxMessageBox("The connect object is no mine!");
#endif
}
/*
* 得到连接时需要保护数据一致性,所以使用 临界对象
*/
CConnObject * CConnPool::GetConnect()
{
CMyEvent cs(m_cs);
CConnObject * pObj = NULL;
for (int i = 0;i < m_listConn.GetSize(); i++)
{
if (!m_listConn[i]->m_bInUse)
{
m_listConn[i]->m_bInUse = TRUE;
pObj = m_listConn[i];
pObj->m_nLastBegin = ::GetTickCount();
return pObj;
}
}
if ((pObj == NULL) &&
(m_listConn.GetSize() < (int)m_ConnMax)) //connect object is no enough!
{
pObj = CreateNewConn();
pObj->m_bInUse = TRUE;
m_listConn.Add(pObj);
return pObj;
}
//连接池已经满载!
return NULL;
}
CConnObject * CConnPool::CreateNewConn()
{
CConnObject * pConn = new CConnObject(this);
if (!pConn->conn.Open("","",_bstr_t(m_strConn)))
return NULL;
return pConn;
}
void CConnPool::TimerProc(HWND hWnd, UINT msg, UINT id, DWORD dwTime)
{
// CHTRDServerApp * pApp = (CHTRDServerApp *)AfxGetApp();
// ASSERT(pPool);
// pPool->OnTimer();
}
/*
* 调度连接池
*/
void CConnPool::OnTimer()
{
DWORD dwTime = ::GetTickCount();
for (int i = 0; i < m_listConn.GetSize(); i++)
{
if (m_listConn[i]->conn.m_Cnn->State == adStateClosed)
{
//delete from pool
delete m_listConn[i];
m_listConn.RemoveAt(i);
TRACE("One conn closed!, delete from pool!/n");
}
else if (!m_listConn[i]->m_bInUse)
{
if (dwTime - m_listConn[i]->m_nLastEnd >= m_nTimeOut)
{
m_listConn[i]->conn.Close();
delete m_listConn[i];
m_listConn.RemoveAt(i);
TRACE("One conn time out!/n");
}
else if (m_listConn[i]->m_nUseCount >= (int)m_nMaxCount)
{
m_listConn[i]->conn.Close();
delete m_listConn[i];
m_listConn.RemoveAt(i);
TRACE("One conn use to much!/n");
}
}
else if (m_listConn[i]->GetTotalUseTime() >= (int)m_nMaxUseTime)
{
m_listConn[i]->conn.Close();
delete m_listConn[i];
m_listConn.RemoveAt(i);
TRACE("One conn use too long/n");
}
}
//检查连接数,小于下限则添加到下限
for (i = m_listConn.GetSize(); i < (int)m_ConnMin;i++)
{
CConnObject * pObj = CreateNewConn();
ASSERT(pObj);
m_listConn.Add(pObj);
}
}
969



被折叠的 条评论
为什么被折叠?



