日期:2014-05-16  浏览次数:20389 次

vc利用ado进行多线程的数据库访问

先描述一下我的问题

           公司开发一套新的打印服务,其中有多个线程可能同时对数据库进行访问,开始的时候用的是一个数据库连接,但是在多个线程同时访问的时候会报数据库异步访问和一些com异常,之后查阅了一些资料,发现在利用ado在进行多线程的数据库访问的时候,最好每个线程对应一个数据库连接,为了方便对这些链接进行管理,自己写了一个数据库连接池,将源码放到这里和大家分享,共同进步,希望能解决一些各位遇到的问题

 

 

#pragma once

 

class DBConnPool
{

private:

 std::map<DWORD, CADODatabase*> m_DbConns;//一个线程对应一个数据库连接的指针
 CComAutoCriticalSection m_SyncRoot;

public:
 CString m_strConn;//数据库连接串

public:

 //DBConnPool(void)
 //{
 //}

 DBConnPool(void)
 {
 }

 ~DBConnPool(void)
 {
  Close();
 }

private:

 BOOL InitDB(CADODatabase* pDbConn)
 {
  if(!pDbConn->Open(m_strConn))
  {
   g_Log.Error("链接数据库失败,请检查连接或配置信息, connstr: %s, func: %s, at: %s(%d)",
    (LPCTSTR)m_strConn, __FUNCTION__, __FILE__, __LINE__);
   return FALSE;
  }

  return TRUE;
 }

 void CloseDB(CADODatabase* pDbConn)
 {
  if(pDbConn != 0)
  {
   if (pDbConn->IsOpen())
   {
    pDbConn->Close();
   }
   delete pDbConn;
   pDbConn = 0;
  }
 }

public:

 //BOOL Init(CString strDbConn)
 //{
 // m_strConn = strDbConn;
 // if ("" != m_strConn)
 // {
 //  return TRUE;
 // }
 // return FALSE;
 //}

 CADODatabase* GetDbConn()
 {
  ATL::CComCritSecLock<CComAutoCriticalSection> lck(m_SyncRoot);

  DWORD dwThreadID = GetCurrentThreadId();

  std::map<DWORD, CADODatabase*> ::iterator it = m_DbConns.find(dwThreadID);
  if (it == m_DbConns.end())
  {
   CADODatabase* pDbConn = new CADODatabase();
   if (InitDB(pDbConn))
   {
    m_DbConns.insert(std::map<DWORD, CADODatabase*>::value_type (dwThreadID,pDbConn));
    return pDbConn;
   }
   return NULL;
  }
  else
  {
   return ((*it).second);
  }
 }

 void Close()
 {
  ATL::CComCritSecLock<CComAutoCriticalSection> lck(m_SyncRoot);

  std::map<DWORD, CADODatabase*> ::iterator it = m_DbConns.begin();
  for(;it != m_DbConns.end(); ++it)
  {
   CloseDB((*it).second);
  }
 }

};