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以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...
随机推荐
- CCS3.3之DM642开发环境建立
使用的仿真器是SEED-XDSUSB2.0/5V. 之前用的是CCS2.2,换成了CCS3.3的. 1.安装CCS3.3.38.在我安装完后,并没有急着升级,升级的程序是SR12_CCS_v3.3_S ...
- 结论: blocking_query 是当前堵塞其他会话正在运行的SQL.而不是原始堵塞SQL
查看当前session线程号 mysql> select connection_id(); +-----------------+ | connection_id() | +---------- ...
- BlockingQueue-线程的阻塞队列
BlockingQueue作为线程容器,可以为线程同步提供有力的保障,其主要用到的方法包括: add(E o); //将指定的元素添加到此队列中(如果立即可行),在成功时返回 true,其他情况则抛出 ...
- dom4j修改xml文件
@SuppressWarnings("unchecked") @Override public void insertCustomInfo(File file, String mo ...
- cocos2d-x学习笔记1——Cocos2D-x 中的核心类
Cocos2D-x 引擎的设计思路是将游戏的各个部分抽象成几个概念,包括导演.场景.布景层和人物精灵,它们之间的关系如图3-1 所示: 导演(CCDirector): 顾名思义,导演类是游戏中的组织者 ...
- Python手动构造Cookie模拟登录后获取网站页面内容
最近有个好友让我帮忙爬取个小说,这个小说是前三十章直接可读,后面章节需要充值VIP可见.所以就需要利用VIP账户登录后,构造Cookie,再用Python的获取每章节的url,得到内容后再使用 PyQ ...
- vijosP1159 岳麓山上打水
vijosP1159 岳麓山上打水 链接:https://vijos.org/p/1159 [思路] 迭代加深搜索+完全背包判断. 自己没有思路,看的别人代码. 总体上讲就是不断增大桶的数目并以之为上 ...
- HW4.29
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
- python爬虫学习(1)__抓取煎蛋图片
#coding=utf-8 #python_demo 爬取煎蛋妹子图在本地文件夹 import requests import threading import time import os from ...
- Preferred Java way to ping a HTTP Url for availability
I need a monitor class that regularly checks whether a given HTTP URL is available. I can take care ...