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 }