ADO简单封装(MFC)
简单封装了一下,不是很严谨。
/************************************************************************/
/* INSTRUCTION: 封装ADO数据库相关操作
DETAILS: 只能在MFC下使用,因此使用了MFC的字符串类
尝试进行了深度封装,但是很多选项(如存储过程)被屏蔽了,适合小型项目使用。
NOTE: ADO数据库访问并不是线程安全的,多个线程公用一个Connection需要线程同步,推荐方法
是每个线程用一个单独的Connection,因此这里没有写成单例模式
*/
/************************************************************************/
#pragma once #include <comdef.h>
#include <list>
#include <set>
#include <string>
#include <boost\lexical_cast.hpp> #import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF") class AdoRecordReader;
class CAdoController
{
public: CAdoController(void)
{
AfxOleInit();
}
~CAdoController(); enum DatabaseProviderEnum
{
Access2000,
ODBC,
Oracle,
SqlServer,
}; bool init();
//连接数据库
bool Connect(const std::string connectstring);
bool Connect(DatabaseProviderEnum database,std::string dataSource,
std::string ip,std::string username,std::string psw); //是否连接成功
bool IsConnected()const
{
return (bool)m_pConnection->State;
} //非SELECT命令,返回影响的行数
int ExecuteNonQuery(const std::string& command); //SELECT命令,返回封装的_RecordSetPtr
AdoRecordReader ExecuteReader(const std::string& command); //TODO:存储过程,待实现
//_RecordsetPtr ExecuteStoreProceduce(const std::string& storeProceduceName); private:
std::string connectStringBuilder( DatabaseProviderEnum database,
std::string &ip, std::string dataSource,
std::string username, std::string psw ); _ConnectionPtr m_pConnection;
_CommandPtr m_pCommand;
_RecordsetPtr m_pRecordset;
}; /*
* _RecordSetPtr相关函数封装,只读实现,不考虑ADO离线层
*/
class AdoRecordReader
{
public:
explicit AdoRecordReader(_RecordsetPtr ptr):
m_recordSetPtr(ptr)
{ }
//使其引用计数+1
AdoRecordReader(const AdoRecordReader& lhs)
{
m_recordSetPtr=lhs.m_recordSetPtr->Clone(adLockOptimistic);
} //减少引用计数
~AdoRecordReader()
{
if (m_recordSetPtr->State)
{
m_recordSetPtr->Close();
m_recordSetPtr.Release();
}
} //移动至下一条记录
bool MoveNext()
{
HRESULT hr;
hr=m_recordSetPtr->MoveNext(); if (!SUCCEEDED(hr))
{
return false;
}
if (m_recordSetPtr->adoEOF)
{
return false;
}
return true;
}
//移动到第一条记录
void MoveFirst()
{
m_recordSetPtr->MoveFirst();
}
//重载下标访问操作符(索引和列名),注意这里下标访问也是只读的
_variant_t operator[](const size_t index)const;
_variant_t operator[](const std::string key)const; //强类型get函数,使用模板来进行强制类型转换
template<typename T>
T get(const size_t index)const
{
return boost::lexical_cast<T>(this->operator[](index));
}
template<typename T>
T get(const std::string key)const
{
return boost::lexical_cast<T>(this->operator[](key));
} //字符串特化
template<>
std::string get<std::string>(const size_t index)const
{
return std::string((char *)(_bstr_t)(this->operator[](index)));
} template<>
std::string get<std::string>(const std::string key)const
{
return std::string((char *)(_bstr_t)(this->operator[](key)));
} //行数
int RecordCount()
{
return m_recordSetPtr->RecordCount;
}
//列数
int FieldCount()
{
return m_recordSetPtr->Fields->Count;
}
private:
_RecordsetPtr m_recordSetPtr;
};
#include "AdoController.h"
#include <iostream>
#include <stdexcept>
#include <boost\algorithm\string.hpp> CAdoController::~CAdoController(void)
{
if (m_pConnection->State)
{
m_pConnection->Close();
}
m_pCommand.Release();
m_pRecordset.Release();
m_pConnection.Release();
} bool CAdoController::init()
{
HRESULT hr; hr=m_pConnection.CreateInstance("ADODB.Connection");
if (!SUCCEEDED(hr))
{
return false;
} hr=m_pCommand.CreateInstance("ADODB.Command");
if (!SUCCEEDED(hr))
{
return false;
} hr=m_pRecordset.CreateInstance("ADODB.Recordset");
if (!SUCCEEDED(hr))
{
return false;
} return true;
} bool CAdoController::Connect( DatabaseProviderEnum database, std::string dataSource,
std::string ip,std::string username,std::string psw)
{
if (m_pConnection->State)
{
m_pConnection->Close();
}
std::string connectstring = connectStringBuilder(database, ip, dataSource, username, psw);
return Connect(connectstring);
} bool CAdoController::Connect( const std::string connectstring )
{
HRESULT hr;
try
{
hr=m_pConnection->Open(_bstr_t(connectstring.c_str()),"","",adModeUnknown);
if (!SUCCEEDED(hr))
{
throw std::exception();
}
return true;
}
catch(_com_error e)
{
std::cerr<<"连接数据库失败!"<<std::endl
<<e.Description()<<std::endl;
return false;
}
} std::string CAdoController::connectStringBuilder( DatabaseProviderEnum database,
std::string &ip, std::string dataSource,
std::string username, std::string psw )
{
std::string connectstring;
switch (database)
{
case CAdoController::Access2000:
connectstring+="Provider=Microsoft.Jet.OLEDB.4.0;DataSource=";
if (ip.length()!=)
{
connectstring+="\\\\"+ip+"\\"+dataSource+";";
}
else
{
connectstring+=dataSource+";";
}
connectstring+=username+";";
connectstring+=psw+";";
break;
case CAdoController::ODBC:
//FIXIT: 远程连接字符串待添加
connectstring+="Provider=MADASQL;DSN="+dataSource+";UID="+
username+";PWD="+psw+";";
break;
case CAdoController::Oracle:
//FIXIT: 远程连接字符串待添加
connectstring+="Provider=MSDAORA;DataSource="+dataSource+";User ID="+
username+";Password="+psw+";";
break;
case CAdoController::SqlServer:
if (username!="")
{
connectstring+="Provider=SQLOLEDB;DataSource="+ip+";Initial Catalog="+
dataSource+";UserID="+username+";Password="+psw+";";
}
else
{
connectstring+="Provider=SQLOLEDB;DataSource=.;Initial Catalog="+
dataSource+";Integrated Security=SSPI;";
}
break;
default:
break;
}
return connectstring;
} int CAdoController::ExecuteNonQuery( const std::string& command )
{
if(boost::istarts_with(command,"select"))
{
throw std::exception("SELECT command queried, you should use ExecuteReader Instead!");
return ;
}
if (!m_pConnection->State)
{
throw std::exception("数据库连接尚未打开");
return ;
}
_variant_t effectLineCount=;
m_pConnection->Execute(_bstr_t(command.c_str()),&effectLineCount,adCmdText); return (int)effectLineCount;
} //执行查询命令,注意这里会抛出异常
AdoRecordReader CAdoController::ExecuteReader( const std::string& command )
{
if (!boost::istarts_with(command,"select"))
{
throw std::exception("Non SELECT command executed, you should user ExecuteNonQuery instead");
}
if (!m_pConnection->State)
{
std::cerr<<"数据库连接尚未打开"<<std::endl;
throw std::exception("数据库未打开");
} _variant_t conn=_variant_t((IDispatch *)m_pConnection,true); try
{
if (m_pRecordset->State)
{
m_pRecordset->Close();
}
m_pRecordset->Open(_variant_t(command.c_str()),conn,adOpenStatic,
adLockOptimistic,adCmdText);
return AdoRecordReader(m_pRecordset);
}
catch(_com_error e)
{
std::cerr<<e.Description()<<std::endl;
throw std::exception("查询出现错误");
}
} _variant_t AdoRecordReader::operator[]( const size_t index ) const
{
try
{
return m_recordSetPtr->GetCollect(_variant_t((long)index));
}
catch(_com_error e)
{
std::cerr<<e.Description()<<std::endl;
return NULL;
}
} _variant_t AdoRecordReader::operator[]( const std::string key ) const
{
try
{
return m_recordSetPtr->GetCollect(_variant_t(key.c_str()));
}
catch(_com_error e)
{
std::cerr<<e.Description()<<std::endl;
return NULL;
}
}
ADO简单封装(MFC)的更多相关文章
- .net core 中简单封装Dapper.Extensions 并使用sqlsuger自动生成实体类
引言 由公司需要使用dapper 同时支持多数据库 又需要支持实体类 又需要支持sql 还需要支持事务 所以采用了 dapper + dapperExtensions 并配套 生成实体类小工具的方 ...
- 学习:简单使用MFC创建对话框窗口
MFC介绍:微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- FMDB简单封装和使用
工具:火狐浏览器+SQLite Manager插件 ; Xcode; FMDB库; 效果: 项目地址: https://github.com/sven713/PackFMDB 主要参考这两篇博客: 1 ...
- Android--Retrofit+RxJava的简单封装(三)
1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...
- okhttp3 get post 简单封装
最近打算在新项目中使用 okhttp3, 简单封装了一下异步 get post 因为 CallBack 也是在子线程中执行,所以用到了 Handler public class MyOkHttpCli ...
- python网页请求urllib2模块简单封装代码
这篇文章主要分享一个python网页请求模块urllib2模块的简单封装代码. 原文转自:http://www.jbxue.com/article/16585.html 对python网页请求模块ur ...
- 对pymysql的简单封装
#coding=utf-8 #!/usr/bin/python import pymysql class MYSQL: """ 对pymysql的简单封装 "& ...
- iOS开发——UI篇OC篇&UITableView简单封装
UITableView简单封装 UITableView时iOS开发中使用最多也是最重的一个UI空间,其实在App Store里面的%80以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...
随机推荐
- [转贴]JAVA:RESTLET开发实例(二)使用Component、Application的REST服务
上一篇文章,我们介绍了基于JAX-RS的REST服务,本篇文章我们介绍不基于JAX-RS的模式.JAX-RS其实就是一个简单的 Application服务.和我们接下来介绍的Application基本 ...
- SPRING IN ACTION 第4版笔记-第二章-003-以Java形式注入Bean、@Bean的用法
1. package soundsystem; import org.springframework.context.annotation.Bean; import org.springframewo ...
- SEH and C++ Exceptions,自定义CSeException
Description of CSeException CSeException class is based on CException class provided by MFC. I overw ...
- 115太酷了,居然出了个TV版客户端
确实,智能电视代表了未来的方向,是智能家居的最重要客户端,TV也能做很多事情呢!!不要忘了这个市场,想想什么服务在TV上是最需要的? http://pc.115.com/tv.html
- 发现一个Doxygen风格的QT帮助
http://cep.xray.aps.anl.gov/software/qt4-x11-4.8.6-browser/classes.html http://cep.xray.aps.anl.gov/ ...
- 为web服务器设置HttpOnly防范XSS攻击
HttpOnly标识是一个可选的.避免利用XSS(Cross-Site Scripting)来获取session cookie的标识.XSS攻击最常见一个的目标是通过获取的session cookie ...
- HDU 5943 Kingdom of Obsession 【二分图匹配 匈牙利算法】 (2016年中国大学生程序设计竞赛(杭州))
Kingdom of Obsession Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
- 在windows下编辑shell脚本注意点
编辑脚本是直接在windows下写的,并没有使用特定的编辑器或者其他工具,所以很有可能出现一些莫名其妙的异常,这些错误是我们眼睛看不到的,遇到这个情况,例如如下异常或者提示语法错误 Java代码 ...
- 进军es6(2)---解构赋值
本该两周之前就该总结的,但最近一直在忙校招实习的事,耽误了很久.目前依然在等待阿里HR面后的结果中...但愿好事多磨!在阿里的某轮面试中面试官问到了es6的掌握情况,说明es6真的是大势所趋,我们更需 ...
- logstash快速入门 (这篇文章很不错 ) | 两种方式往logstash传输数据实例:Apache 日志(从文件获取)、Syslog方式
原文地址:http://www.2cto.com/os/201411/352015.html 原文地址:http://logstash.net/docs/1.4.2/tutorials/getting ...