MFC操作SQL数据库的类_sqlmfc 数据集-程序员宅基地



#pragma once


#import "C:\\Program Files (x86)\\Common Files\\System\\ado\\msado15.dll" no_namespace
rename("EOF","ADOEOF") rename("BOF","ADOBOF")

#define DATEBASE_TYPE_ACCESS 0
#define DATEBASE_TYPE_SQL2000 1
#define DATEBASE_TYPE_SQL2005 2
#define DATEBASE_TYPE_OTHER 3

.h文件
class CDao
{
public:
CDao(void);
BOOL InitCom(); //初始化com组件
void releaseCom(); //释放com组件
public:
~CDao(void);
//打开数据库并进行初始化
BOOL OpenDateBase(CString strDateBaseName,int nDataType,CString strUser,CString strPassWord,CString strIP);
BOOL CStringToDataType(CString strValue,int nDataType, VARIANT *pVar);//CString转成其他数据类型
BOOL GetData(CString strSql,CString *strQueryCloum,int nCloumNum,CStringArray& strDataValue);//从数据库获取数据
CString DataToCStringType(VARIANT Var);
BOOL AddData(CString strTableName,CStringArray& strCloumValue,int nCloumNum);
BOOL EditData(CString strSQL, int nColumnNum, CString* pStrFieldName, CStringArray &saValue);
BOOL DeleteData(CString strSQL);

public:
_ConnectionPtr m_pConnection; //连接数据库的指针对象
_RecordsetPtr m_pRecordset; //操作记录集的指针对象
_CommandPtr m_pCommandmsg; //SQL命令的指针对象
private:
BOOL m_binitComFlag;
CString m_strErrorMsg; //错误信息
CString m_strConnect; //连接串
};

.cpp文件

#include "StdAfx.h"
#include <atlimage.h>
#include "Dao.h"


CDao::CDao(void)
{
m_binitComFlag = FALSE;
InitCom();
}

CDao::~CDao(void)
{
releaseCom();
}

BOOL CDao::InitCom() //初始化com组件
{
#if _WIN32_WINNT > 0x500
//保留字(必须为null) ,加载方式 COINIT_MULTITHREADED多线程的方式加载
// 以多线程方式打开com通道
::CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
::CoInitialize(NULL);
#endif
m_binitComFlag = TRUE;
return TRUE;
}
void CDao::releaseCom() //释放com组件
{
if (m_binitComFlag)
{
::CoUninitialize();
}
}

//哪个什么类型的数据库
BOOL CDao::OpenDateBase(CString strDateBaseName,int nDataType,CString strUser,CString strPassWord,CString strIP)
{
//"colin",DATEBASE_TYPE_SQL2005,"sa","sa","127.0.0.1,2433"
if (nDataType == DATEBASE_TYPE_ACCESS)
{
CFileFind filefind;
BOOL bFind = filefind.FindFile(strDateBaseName);

if (!bFind)
{
m_strErrorMsg = _T("找不到数据库");
return FALSE;
}
else
{
m_strConnect.Format(_T("provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s"),strDateBaseName);
}
}
else if (nDataType == DATEBASE_TYPE_SQL2000)
{
m_strConnect.Format(_T("Driver={SQL Server};Server=%s;Uid=%s;Pwd=%s;Database=%s"),strIP,strUser,strPassWord,strDateBaseName);
}
else if (nDataType == DATEBASE_TYPE_SQL2005)
{
m_strConnect.Format(_T("Driver={SQL Native Client};Server=%s;Uid=%s;Pwd=%s;Database=%s"),strIP,strUser,strPassWord,strDateBaseName);
}
else
{
m_strErrorMsg = _T("没有合适的连库串");
return FALSE;
}


//实例化指针对象
HRESULT hRes;
//把CString转换成com组件里的字符串变量,COM能和数据库内容进行通信
_bstr_t bstrConnection(m_strConnect);
_bstr_t bstrUser(strUser);
_bstr_t bstrPassword(strPassWord);

try
{
//创建连接对象 序列码
hRes = m_pConnection.CreateInstance(__uuidof(Connection));
if (!SUCCEEDED(hRes))
{
m_strErrorMsg = _T("实例化连接指针对象失败");
return FALSE;
}

//连接数据库(连库串,用户名,密码,打开方式)
//字符串要用的是com组件的字符串 adModeShareDenyNone多用户共同可以访问一个数据库
hRes = m_pConnection->Open(bstrConnection,bstrUser,bstrPassword,adModeShareDenyNone);
if (!SUCCEEDED(hRes))
{
m_strErrorMsg = _T("打开数据库失败");
return FALSE;
}

//实例化数据集指针对象
hRes = m_pRecordset.CreateInstance(__uuidof(Recordset));
if (!SUCCEEDED(hRes))
{
m_strErrorMsg = _T("实例化数据集指针对象失败");
return FALSE;
}
//实例化命令集指针对象
hRes = m_pCommandmsg.CreateInstance(__uuidof(Command));
if (!SUCCEEDED(hRes))
{
m_strErrorMsg = _T("实例化命令集指针对象失败");
return FALSE;
}

}catch(_com_error *e)
{
AfxMessageBox(e->Description());
m_strErrorMsg.Format(_T("%s"),e->Description());
return FALSE;
}

return TRUE;
}
BOOL CDao::GetData(CString strSql,CString *strQueryCloum,int nCloumNum,CStringArray& strDataValue)
{
HRESULT het;
//_bstr_t 字符串 _variant_t 多种数据类型集合 vt类型 ..value值 //com
_bstr_t bstrSql = strSql; //执行sql
_bstr_t bstrConnect = m_strConnect; //连库串
_bstr_t bstrQueryCloum; //列名

Fields *fields;
FieldPtr fieldPtr;

CString strValue;
_variant_t varBLOB;
try
{
//1.打开表
/*m_pRecordset->Open(查询SQL语句,连接串,打开方式,数据源更新时如何锁定结果集,以什么形式传入)
打开方式:
adOpenUnspecified = -1, 默认的方式打开
adOpenForwardOnly = 0, 向前移动的游标打开
adOpenKeyset = 1, 以键值打开
adOpenDynamic = 2, 当你添加数据时别人也有可能往这个表添加数据,谁在前谁添加到前面(多人用数据库时)
adOpenStatic = 3 别人也想往里面添加数据一直停留在打开时候

锁定结果集方式:
adLockReadOnly = 1, 只读的不能改变数据
adLockPessimistic = 2, (保守式锁定)逐个 – 编辑时立即锁定数据源的纪录
adLockOptimistic = 3, (开放式锁定)逐个 – 只在调用update方法时才锁定纪录
adLockBatchOptimistic = 4 开方式 可以更新一批数据更新模式
+ bstrConnect {"Driver={SQL Native Client};Server=192.168.1.92,2433;Uid=sa;Pwd=sa;Database=colin0716" (1)} _bstr_t
+ bstrSql {"select * from student" (1)} _bstr_t

*/
het = m_pRecordset->Open(bstrSql,bstrConnect,adOpenDynamic,adLockOptimistic,adCmdText);
if (!SUCCEEDED(het))
{
AfxMessageBox(_T("打开表失败"));
m_strErrorMsg = _T("查询表失败");
return FALSE;
}
//循环结果
while(!m_pRecordset->ADOEOF)
{
for(int i=0;i<nCloumNum;i++)
{
bstrQueryCloum = strQueryCloum[i];
fields = m_pRecordset->GetFields();

fieldPtr = fields->GetItem(bstrQueryCloum);

varBLOB = fieldPtr->GetValue();

//long nSize =fieldPtr->ActualSize;


//注意图片名称必须为图片流的前一个字段
//strValue = DataToCStringType(varBLOB,nSize,strValue);
strValue = DataToCStringType(varBLOB);
strDataValue.Add(strValue);
//varBLOB.Detach();
}
m_pRecordset->MoveNext();
}

m_pRecordset->Close();
}
catch(_com_error *e)
{
m_strErrorMsg = e->ErrorMessage();
AfxMessageBox(e->ErrorMessage());
}

return TRUE;
}
CString CDao::DataToCStringType(VARIANT Var)
{
CString strValue;
switch(Var.vt)
{
case VT_BOOL:
strValue.Format(_T("%d"), Var.boolVal);
break;
case VT_I4:
strValue.Format(_T("%d"), Var.intVal);
break;
case VT_R8:
case VT_DECIMAL:

strValue.Format(_T("%0.2f"), Var.dblVal);
break;
case VT_BSTR:
strValue= Var.bstrVal;
break;
default:
strValue = _T("");
break;
}

return strValue;
}
BOOL CDao::AddData(CString strTableName,CStringArray& strCloumValue,int nCloumNum)
{
//校验
if (strTableName.IsEmpty() || strCloumValue.GetCount() == 0 || nCloumNum == 0)
{
m_strErrorMsg = _T("参数错误");
AfxMessageBox(_T("输入参数错误,请重新输入"));
return FALSE;
}

CString strQuery;
strQuery.Format(_T("select * from [%s]"),strTableName);

//自带的字符串类型
_bstr_t bstrQuery(strQuery);
_bstr_t bstrCource(m_strConnect);

HRESULT hres;
Fields *pFiles = NULL;
//ado把所有的数据类型都写在VARIANT这里面
VARIANT varIndex;
varIndex.vt = VT_I4; //R代表float CY==钱数 VT_代表的都是comADO代表的数据类型

Field *pFile = NULL;
DataTypeEnum dataType;
VARIANT varValue;
try
{
//打开表
hres = m_pRecordset->Open(bstrQuery,bstrCource,adOpenDynamic,adLockBatchOptimistic,adCmdText);
if (!SUCCEEDED(hres))
{
m_strErrorMsg = _T("打开表失败");
return FALSE;
}
else
{
//计算添加记录的行数
int nRosNum = (int)(strCloumValue.GetCount()/nCloumNum);
if(nRosNum <= 0 )
{
m_strErrorMsg = _T("参数个数错误");
AfxMessageBox(_T("输入参数错误,请重新输入"));
return FALSE;
}
//添加记录 循环行
for (int i=0; i<nRosNum; i++)
{
//告诉记录集要添加记录
m_pRecordset->AddNew();
//把记录一列一列的写进去
for (int ncloum=0;ncloum<nCloumNum;ncloum++)
{
//传入的都是字符串 我要先得到列的数据类型 然后在做相应的转换 再把数据添加到数据库里
//在数据库里列都是以集合形式存在的,所以先要得到所有的列,在从中得到每一个列
//Fields *pFiles 是个双指针
//1.得到所有的列
m_pRecordset->get_Fields(&pFiles);

//2.得到具体的列
//ADO的COM对数据库编程 除了定义了字符串其他的没有具体定义 ado把所有的数据类型都写在VARIANT这里面
varIndex.intVal = ncloum;
pFiles->get_Item(varIndex,&pFile);

//3.得到列(字段)对应的数据类型
pFile->get_Type(&dataType);

//4.转换 CString--》对应的类型 0 1 2 3 4 5 3
if (CStringToDataType(strCloumValue.GetAt(ncloum+i*nCloumNum),dataType,&varValue))
{
//5.添加记录
pFile->put_Value(varValue);
if (varValue.vt == (VT_UI1|VT_ARRAY))
{
SafeArrayDestroy(varValue.parray);
}
}

}
//更新数据
m_pRecordset->UpdateBatch(adAffectCurrent);
}
//关闭记录集 如果不关闭就会被一直占用,就打不开了
/*if (pStrReturnID)
{
m_pRecordset->MoveLast();
m_pRecordset->get_Fields(&pFiles);

varIndex.intVal = 0;
pFiles->get_Item(varIndex,&pFile);
VARIANT varKey;
pFile->get_Value(&varKey);

pStrReturnID->Format(_T("%d"),varKey.intVal);
}*/

m_pRecordset->Close();//记录集被关闭
}
}catch(_com_error *e)
{
AfxMessageBox(e->Description());
m_strErrorMsg.Format(_T("%s"),e->Description());
return FALSE;
}
return TRUE;
}
BOOL CDao::CStringToDataType(CString strValue,int nDataType, VARIANT *pVar)
{
switch(nDataType)
{
case adInteger: //整形
pVar->vt = VT_I2;
pVar->intVal = _ttoi(strValue);
break;
case adBoolean: //BOOL类型
pVar->vt = VT_BOOL;
pVar->bVal = _ttoi(strValue);
break;
case adSingle: //单精度
pVar->vt = VT_R4;
pVar->fltVal = (float)_tstof(strValue);
break;
case adDouble: //双精度
pVar->vt = VT_R8;
pVar->dblVal = _tstof(strValue);
break;
case adBSTR: //字符串
case adChar:
case adVarChar:
case adVarWChar:
case adWChar:
case adLongVarWChar:
case adLongVarChar:
pVar->vt = VT_BSTR;
pVar->bstrVal = (bstr_t)strValue;
break;
case adLongVarBinary:
//SaveImg(strValue,pVar);
break;
default:
pVar->vt = VT_EMPTY;
break;
}
return TRUE;
}

//修改数据的查询语句 列的个数, 修改的列名,列名对应值
BOOL CDao::EditData(CString strSQL, int nColumnNum, CString* pStrFieldName, CStringArray &saValue)
{
//todu:校验

int nIndex = 0; //列的索引
int nCount = 0; //修改的总数
int nTotal = (int)saValue.GetCount(); //一共修改的个数

HRESULT hRet;
_variant_t varFieldName;
_variant_t varValue;

_bstr_t bstrQuery = strSQL;
_bstr_t bstrConnent = m_strConnect;

try
{
hRet = m_pRecordset->Open(bstrQuery, bstrConnent, adOpenDynamic, adLockOptimistic, adCmdText);
if(!SUCCEEDED(hRet))
{
m_strErrorMsg = _T("打开表失败!");
return FALSE;
}
if (m_pRecordset->ADOEOF)
{
m_strErrorMsg = _T("没有选择修改的行");
m_pRecordset->Close();
return FALSE;
}
Fields *pFiles = NULL;
//ado把所有的数据类型都写在VARIANT这里面
VARIANT varIndex;
varIndex.vt = VT_I4; //R代表float CY==钱数 VT_带表的都是comADO代表的数据类型

Field *pFile = NULL;

while(!m_pRecordset->ADOEOF)
{
修改哪一列 s# sname 1 'ss' 2 'ss2' stringarr 4 2
varFieldName.SetString((bstr_t)pStrFieldName[nIndex]);

varValue.SetString((bstr_t)saValue.GetAt(nCount));


m_pRecordset->Update(varFieldName,varValue);
nIndex++;
nCount++;
if(nIndex>=nColumnNum)
{
nIndex = 0;
m_pRecordset->MoveNext();
}

if (nColumnNum == 1)
{
if(nCount == nTotal)
{
break;
}
}
else
{
if(nCount > nTotal)
{
break;
}
}
}
m_pRecordset->Close();
}
catch(_com_error *e)
{
m_strErrorMsg = e->ErrorMessage();
AfxMessageBox(e->Description());
return FALSE;
}

return TRUE;
}
BOOL CDao::DeleteData(CString strSQL)
{
HRESULT hRet;

_bstr_t bstrQuery = strSQL;
_bstr_t bstrConnent = m_strConnect;

try
{
hRet = m_pRecordset->Open(bstrQuery, bstrConnent, adOpenDynamic, adLockOptimistic, adCmdText);
if(!SUCCEEDED(hRet))
{
m_strErrorMsg = _T("打开表失败!");
return FALSE;
}
while(!m_pRecordset->ADOEOF)
{
m_pRecordset->Delete(adAffectCurrent);
m_pRecordset->MoveNext();
}

m_pRecordset->Close();
}
catch(_com_error *e)
{
AfxMessageBox(e->Description());
return FALSE;
}
return TRUE;
}

首先,我们需要定义个CDao 对象,在其构造函数会初始化Com,在析构函数会释放Com,那么我们应该在什么地方来定义CDao 对象呢?

这个变量必须能够在全局使用,在应用程序启动的时候开启数据库,而在应用程序关闭的时候关闭数据库。mfc中有个全局对象theApp,可以在应用程序类中定义CDao 对象。

今天基本上完成了在mfc中对数据库的增删改查操作。心里非常的开心,加油!



http://www.2cto.com/database/201401/271174.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/myiszjf/article/details/51857483

智能推荐

没有第三方控件用RadioGroup做轮播图--MainActivity 主页面和布局_mainactivity类怎么转成radiogroup类-程序员宅基地

文章浏览阅读405次。没有第三方控件用RadioGroup做轮播图--MainActivity 主页面和布局_mainactivity类怎么转成radiogroup类

Spark闭包与序列化_闭包序列化-程序员宅基地

文章浏览阅读1.9w次,点赞9次,收藏22次。本文原文出处: http://blog.csdn.net/bluishglc/article/details/50945032 严禁任何形式的转载,否则将委托CSDN官方维护权益!在Spark的官方文档再三强调那些将要作用到RDD上的操作,都会被分发到各个worker节点上去执行,我们都知道,这些操作实际上就是一些函数和涉及的变量组成的闭包,这里显然涉及到一个容易被忽视的问题:闭包的“序列化”。显然_闭包序列化

Unity ECS Manual [17]_unity ecs1.0-程序员宅基地

文章浏览阅读123次。Job dependencies  Unity根据系统读取和写入的ECS组件来分析每个系统的数据依赖性。如果一个在框架中较早更新的系统读取了后来的系统所写的数据,或者写了后来的系统所读的数据,那么第二个系统就会依赖第一个系统。为了防止竞争条件,作业调度器在运行一个系统的作业之前,要确保该系统所依赖的所有作业已经完成。  一个系统的Dependency属性是一个JobHandle,代表了该系统的ECS相关依赖关系。在OnUpdate()之前,Dependency属性反映了系统对先前作业的传入依赖关系。默认_unity ecs1.0

【干货合集】看完这16篇文章,不再做敏捷项目管理上的小白!_项目管理干货 site:csdn.net-程序员宅基地

文章浏览阅读1.1k次。原文链接:点击打开链接摘要: 流行技术大狂欢,5月29日即将召开的第二届研发效能嘉年华,带来了前沿技术理念及实践技术成果分享。本次峰会将有10位技术大咖进行干货分享,多角度,不同领域的带领大家了解高效研发。项目管理的主流模式有哪几种?传统项目管理通常采用的是瀑布式、部分迭代开发模式,要求在项目建设时,需求足够明确、文档足够规范,迭代过程中需求变更越多、越晚,对项目影响越大,会影响到项目的交付质量。..._项目管理干货 site:csdn.net

大数据(二十七):Sqoop常用命令和公用参数_大数据 公参-程序员宅基地

文章浏览阅读211次。一、常用命令列举 命令 类 说明 import ImportTool 将数据导入到集群 export ExportTool 将集群数据导出 codegen CodeGenTool ..._大数据 公参

基于MAC地址的安全配置与管理实战_如何防范mac地址泛滥-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏10次。MAC地址是网络设备中不变的物理地址,基于MAC地址的接入控制成了最直接,甚至可能是大多数情况下最有效的控制手段。在二层交换网络中,是通过依靠保存在交换机中的MAC地址表来进行寻址的,这时如果控制交换机中存储的MAC地址表就可以控制一些非法设备的接入,让其他设备不能与他进行通信。在华为S系列交换机中,为了实现这个目的提供了多种基于MAC地址的安全手段,如限制接口学习MAC地址表项的数量,限制交..._如何防范mac地址泛滥

随便推点

cookie和session机制之间的区别与联系-程序员宅基地

文章浏览阅读1.1w次。具体来说cookie机制采用的是在客户端保持状态的方案。它是在用户端的会话状态的存贮机制,他需要用户打开客户端的cookie支持。cookie的作用就是为了解决HTTP协议无状态的缺陷所作的努力.而session机制采用的是一种在客户端与服务器之间保持状态的解决方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到

微信小程序初识---地图开发_微信公小程序地图开发-程序员宅基地

文章浏览阅读2k次。微信小程序似乎比较火,很多公司除了自家app外都要给自家再弄个小程序,于是乎空余时间就试了试小程序,现记录下地图页面的开发。小程序官方文档也比较全,基本上面的东西都有,有前端开发经验的上手更简单。先上图 : 1.层级结构: 小程序类似于app,以页面为单位,每个页面包含4个文件: .js .json .wxml .wxss 为后缀的文件,官方文_微信公小程序地图开发

Anaconda详细安装及使用教程(带图文)-程序员宅基地

文章浏览阅读10w+次,点赞1.4k次,收藏7.9k次。Anacond的介绍Anaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。因为包含了大量的科学包,Anaconda的下载文件比较大(约531 MB),如果只需要某些包,或者需要节省带宽或存储空间,也可以使用Miniconda这个较小的发行版(仅包含conda和Python)。Conda是一个开源的包、环境管理器,可以用于..._anaconda

JDK的动态代理(附带完整代码demo)_jdk动态代理demo-程序员宅基地

文章浏览阅读1.5k次。JDK的代理,实际上是对Java接口(Interface)的代理,而且只能对接口进行代理,达到的效果是,当调用指定接口的指定方法时,会执行特定的操作。例如,HelloService是一个接口,public String sayHello(String msg)是该接口的其中一个方法,当代码调用该接口的sayHello方法时,会执行规定好的动作。这里会有一个问题,HelloService接口的实现类是从哪里来的呢?这里HelloService接口的实现类是由代理动态生成的实现类。所以想为一个接口生成代理,需要_jdk动态代理demo

设计模式—组合与聚合详解_聚合是菱形空心吗-程序员宅基地

文章浏览阅读2.2k次。在UML类图中,聚合是空心菱形,组合是实心菱形。简单来说:组合的关系就像一个学生和他的各个器官,手、脚、鼻子、眼睛等器官组合成了一个学生,这些器官离开了学生这个个体,也就失去了意义,无法单独生存,因此,组合关系的类具有相同的生命周期,它们的联系更加紧密。而聚合就像一个班级有许多学生构成,学生离开了班级,作为一个个体仍然能够存活。聚合案例public ClassRoom{ public..._聚合是菱形空心吗

【备战金三银四】2022史上最全Android 面试题_2022 最全android面试题合集-程序员宅基地

文章浏览阅读499次。小编经历过这么多年的摸爬滚打,面试过也被面试过。现总结与归纳Android开发相关面试题:初级面试题:1、Activity启动模式有哪些,分别有什么不同?2、Service启动模式有哪些,对应的生命周期?IntentService呢?3、ContentProvider的作用,是否支持多线程和多进程4、Broadcast的注册方式,对应的生命周期是什么,有序和无序那种可以中断广播?5、AsyncTask的作用,如何使用(包括有哪些方法,能说出同步异步,能说出不同Android版本下的区别加分)6_2022 最全android面试题合集