ADO简单封装(MFC)

简单封装了一下,不是很严谨。

  1 /************************************************************************/
  2 /* INSTRUCTION: 封装ADO数据库相关操作
  3    DETAILS: 只能在MFC下使用,因此使用了MFC的字符串类
  4             尝试进行了深度封装,但是很多选项(如存储过程)被屏蔽了,适合小型项目使用。
  5    NOTE: ADO数据库访问并不是线程安全的,多个线程公用一个Connection需要线程同步,推荐方法
  6    是每个线程用一个单独的Connection,因此这里没有写成单例模式
  7 */
  8 /************************************************************************/
  9 #pragma once
 10 
 11 #include <comdef.h>
 12 #include <list>
 13 #include <set>
 14 #include <string>
 15 #include <boost\lexical_cast.hpp>
 16 
 17 #import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
 18 
 19 class AdoRecordReader;
 20 class CAdoController
 21 {
 22 public:
 23 
 24     CAdoController(void)
 25     {
 26         AfxOleInit();
 27     }
 28     ~CAdoController();
 29 
 30     enum DatabaseProviderEnum
 31     {
 32         Access2000,
 33         ODBC,
 34         Oracle,
 35         SqlServer,
 36     };
 37 
 38     bool init();
 39     //连接数据库
 40     bool Connect(const std::string connectstring);
 41     bool Connect(DatabaseProviderEnum database,std::string dataSource,
 42         std::string ip,std::string username,std::string psw);
 43 
 44     //是否连接成功
 45     bool IsConnected()const
 46     {
 47         return (bool)m_pConnection->State;
 48     }
 49 
 50     //非SELECT命令,返回影响的行数
 51     int ExecuteNonQuery(const std::string&  command);
 52 
 53     //SELECT命令,返回封装的_RecordSetPtr
 54     AdoRecordReader ExecuteReader(const std::string& command);
 55 
 56     //TODO:存储过程,待实现
 57     //_RecordsetPtr ExecuteStoreProceduce(const std::string& storeProceduceName);
 58 
 59 private:
 60     std::string connectStringBuilder( DatabaseProviderEnum database, 
 61          std::string &ip, std::string dataSource,
 62         std::string username, std::string psw );
 63 
 64     _ConnectionPtr m_pConnection;
 65     _CommandPtr m_pCommand;
 66     _RecordsetPtr m_pRecordset;
 67 };
 68 
 69 /*
 70  *    _RecordSetPtr相关函数封装,只读实现,不考虑ADO离线层
 71  */
 72 class AdoRecordReader
 73 {
 74 public:
 75     explicit AdoRecordReader(_RecordsetPtr ptr):
 76         m_recordSetPtr(ptr)
 77     {
 78 
 79     }
 80     //使其引用计数+1
 81     AdoRecordReader(const AdoRecordReader& lhs)
 82     {
 83         m_recordSetPtr=lhs.m_recordSetPtr->Clone(adLockOptimistic);
 84     }
 85 
 86     //减少引用计数
 87     ~AdoRecordReader()
 88     {
 89         if (m_recordSetPtr->State)
 90         {
 91             m_recordSetPtr->Close();
 92             m_recordSetPtr.Release();
 93         }
 94     }
 95     
 96     //移动至下一条记录
 97     bool MoveNext()
 98     {
 99         HRESULT hr;
100         hr=m_recordSetPtr->MoveNext();
101 
102         if (!SUCCEEDED(hr))
103         {
104             return false;
105         }
106         if (m_recordSetPtr->adoEOF)
107         {
108             return false;
109         }
110         return true;
111     }
112     //移动到第一条记录
113     void MoveFirst()
114     {
115         m_recordSetPtr->MoveFirst();
116     }
117     //重载下标访问操作符(索引和列名),注意这里下标访问也是只读的
118     _variant_t operator[](const size_t index)const;
119     _variant_t operator[](const std::string key)const;
120 
121     //强类型get函数,使用模板来进行强制类型转换
122     template<typename T>
123     T get(const size_t index)const
124     {
125         return boost::lexical_cast<T>(this->operator[](index));
126     }
127     template<typename T>
128     T get(const std::string key)const
129     {
130         return boost::lexical_cast<T>(this->operator[](key));
131     }
132 
133     //字符串特化
134     template<>
135     std::string get<std::string>(const size_t index)const
136     {
137         return std::string((char *)(_bstr_t)(this->operator[](index)));
138     }
139 
140     template<>
141     std::string get<std::string>(const std::string key)const
142     {
143         return std::string((char *)(_bstr_t)(this->operator[](key)));
144     }
145 
146     //行数
147     int RecordCount()
148     {
149         return m_recordSetPtr->RecordCount;
150     }
151     //列数
152     int FieldCount()
153     {
154         return m_recordSetPtr->Fields->Count;
155     }
156 private:
157     _RecordsetPtr m_recordSetPtr;
158 };
  1 #include "AdoController.h"
  2 #include <iostream>
  3 #include <stdexcept>
  4 #include <boost\algorithm\string.hpp>
  5 
  6 CAdoController::~CAdoController(void)
  7 {
  8     if (m_pConnection->State)
  9     {
 10         m_pConnection->Close();
 11     }
 12     m_pCommand.Release();
 13     m_pRecordset.Release();
 14     m_pConnection.Release();
 15 }
 16 
 17 bool CAdoController::init()
 18 {
 19     HRESULT hr;
 20 
 21     hr=m_pConnection.CreateInstance("ADODB.Connection");
 22     if (!SUCCEEDED(hr))
 23     {
 24         return false;
 25     }
 26 
 27     hr=m_pCommand.CreateInstance("ADODB.Command");
 28     if (!SUCCEEDED(hr))
 29     {
 30         return false;
 31     }
 32 
 33     hr=m_pRecordset.CreateInstance("ADODB.Recordset");
 34     if (!SUCCEEDED(hr))
 35     {
 36         return false;
 37     }
 38 
 39     return true;
 40 }
 41 
 42 bool CAdoController::Connect( DatabaseProviderEnum database, std::string dataSource,
 43                              std::string ip,std::string username,std::string psw)
 44 {
 45     if (m_pConnection->State)
 46     {
 47         m_pConnection->Close();
 48     }
 49     std::string connectstring = connectStringBuilder(database, ip, dataSource, username, psw);
 50     return Connect(connectstring);
 51 }
 52 
 53 bool CAdoController::Connect( const std::string connectstring )
 54 {
 55     HRESULT hr;
 56     try
 57     {
 58         hr=m_pConnection->Open(_bstr_t(connectstring.c_str()),"","",adModeUnknown);
 59         if (!SUCCEEDED(hr))
 60         {
 61             throw std::exception();
 62         }
 63         return true;
 64     }
 65     catch(_com_error e)
 66     {
 67         std::cerr<<"连接数据库失败!"<<std::endl
 68             <<e.Description()<<std::endl;
 69         return false;
 70     }
 71 }
 72 
 73 std::string CAdoController::connectStringBuilder( DatabaseProviderEnum database, 
 74                                                  std::string &ip, std::string dataSource,
 75                                                  std::string username, std::string psw )
 76 {
 77     std::string connectstring;
 78     switch (database)
 79     {
 80     case CAdoController::Access2000:
 81         connectstring+="Provider=Microsoft.Jet.OLEDB.4.0;DataSource=";
 82         if (ip.length()!=0)
 83         {
 84             connectstring+="\\\\"+ip+"\\"+dataSource+";";
 85         }
 86         else
 87         {
 88             connectstring+=dataSource+";";
 89         }
 90         connectstring+=username+";";
 91         connectstring+=psw+";";
 92         break;
 93     case CAdoController::ODBC:
 94         //FIXIT: 远程连接字符串待添加
 95         connectstring+="Provider=MADASQL;DSN="+dataSource+";UID="+
 96             username+";PWD="+psw+";";
 97         break;
 98     case CAdoController::Oracle:
 99         //FIXIT: 远程连接字符串待添加
100         connectstring+="Provider=MSDAORA;DataSource="+dataSource+";User ID="+
101             username+";Password="+psw+";";
102         break;
103     case CAdoController::SqlServer:
104         if (username!="")
105         {
106             connectstring+="Provider=SQLOLEDB;DataSource="+ip+";Initial Catalog="+
107                 dataSource+";UserID="+username+";Password="+psw+";";
108         }
109         else
110         {
111             connectstring+="Provider=SQLOLEDB;DataSource=.;Initial Catalog="+
112                 dataSource+";Integrated Security=SSPI;";
113         }
114         break;
115     default:
116         break;
117     }    
118     return connectstring;
119 }
120 
121 int CAdoController::ExecuteNonQuery( const std::string& command )
122 {
123     if(boost::istarts_with(command,"select"))
124     {
125         throw std::exception("SELECT command queried, you should use ExecuteReader Instead!");
126         return 0;
127     }
128     if (!m_pConnection->State)
129     {
130         throw std::exception("数据库连接尚未打开");
131         return 0;
132     }
133     _variant_t effectLineCount=0;
134     m_pConnection->Execute(_bstr_t(command.c_str()),&effectLineCount,adCmdText);
135 
136     return (int)effectLineCount;
137 }
138 
139 //执行查询命令,注意这里会抛出异常
140 AdoRecordReader CAdoController::ExecuteReader( const std::string& command )
141 {
142     if (!boost::istarts_with(command,"select"))
143     {
144         throw std::exception("Non SELECT command executed, you should user ExecuteNonQuery instead");
145     }
146     if (!m_pConnection->State)
147     {
148         std::cerr<<"数据库连接尚未打开"<<std::endl;
149         throw std::exception("数据库未打开");
150     }
151 
152     _variant_t conn=_variant_t((IDispatch *)m_pConnection,true);
153 
154     try
155     {
156         if (m_pRecordset->State)
157         {
158             m_pRecordset->Close();
159         }
160         m_pRecordset->Open(_variant_t(command.c_str()),conn,adOpenStatic,
161             adLockOptimistic,adCmdText);
162         return AdoRecordReader(m_pRecordset);
163     }
164     catch(_com_error e)
165     {
166         std::cerr<<e.Description()<<std::endl;
167         throw std::exception("查询出现错误");
168     }
169 }
170 
171 _variant_t AdoRecordReader::operator[]( const size_t index ) const
172 {
173     try
174     {
175         return m_recordSetPtr->GetCollect(_variant_t((long)index));
176     }
177     catch(_com_error e)
178     {
179         std::cerr<<e.Description()<<std::endl;
180         return NULL;
181     }
182 }
183 
184 _variant_t AdoRecordReader::operator[]( const std::string key ) const
185 {
186     try
187     {
188         return m_recordSetPtr->GetCollect(_variant_t(key.c_str()));
189     }
190     catch(_com_error e)
191     {
192         std::cerr<<e.Description()<<std::endl;
193         return NULL;
194     }
195 }

 

posted @ 2013-09-12 14:45  生无所息  阅读(3081)  评论(0编辑  收藏  举报