记录文章_updatedata(true);//把界面上的数据传递给底层代码 cstring strsno, -程序员宅基地

技术标签: 数据库  

    数据库操作接口比较   (ADO   OLED  ODBC  DAO)           http://blog.csdn.net/ithomer/article/details/6624684

     VC操作数据库sql sever                                                             http://blog.csdn.net/yuzhongchun/article/details/8177551

      数据库操作接口比较   (ADO   OLED  ODBC  DAO)         http://www.2cto.com/database/201402/281477.html

ADO、OLEDB、ODBC之间的关系图

以下所记录的连接数据库的方式都是微软提出的,都是微软的东西,window下可以,至于linux就不知道了

下面是微软提出的所有连接方式:
ODBC(Open DataBase Connectivity)开放数据库互联。是由微软主导的数据库链接标准,只支持关系型数据库。
DAO(Data Access Object)数据访问对象。不提供远程访问功能。
RDO(Remote Data Object)远程数据对象。速度快,支持SQL Server存储过程。
OLEDB(Object Linking and Embedding DataBase)对象链接和嵌入数据库。

ADO(ActiveX Data Object)ActiveX数据对象。

使用中,我们一般用OLE-DB和ADO替代DAO和RDO,DAO和RDO我也没用过,所以下面主要记录下ADO、OLEDB、ODBC之间的关系。

<img src="http://www.2cto.com/uploadfile/Collfiles/20140226/2014022609272165.jpg" alt="l逗'€嗔 �-畨�:棫玓m�夌y薭�+rn絵鱜!╧y" kf"="" target="_blank" class="keylink" style="border-width: 0px; padding: 0px; margin: 0px auto; list-style: none; display: block; width: 630px; height: 360px;">编程
接口)。这些API利用 SQL来完成其大部分任务。ODBC本身也提供了对SQL语言的支持,用户可以直接将SQL语句送给ODBC。这个标准相对来说
是偏底层的,而且只支持关系型数据库


OLE DB(Object Linking and Embedding, Database,对象连接嵌入数据库)
1997 年, Microsoft 的一个战略性系统级编程接口(COM 接口,对各种数据库管理系统服务进行封装),是微软的战略性的通向不同的数据
源的低级应用程序接口,用于管理整个组织内的数据。OLE DB不仅包括微软资助的标准数据接口开放数据库连通性(ODBC)的结构化问题语
言(SQL)能力,还具有面向其他非SQL数据类型的通路。作为微软的组件对象模型(COM)的一种设计,OLE DB是一组读写数据的方法。OLE 
DB 可用于访问关系型和非关系型信息源,例如主机 ISAM/VSAM 和层次数据库,电子邮件和文件系统存储,文本、图形和地理数据以及自义业务对象。

ADO(ActiveX Data Object,活动数据对象)
1996 年,ADO是DAO/RDO的后继产物,是一个用于存取数据源的COM组件,是Microsoft提出的高层应用程序接口(API)用以实现访问关系或非
关系数据库中的数据。允许开发人员编写访问数据的代码而不用关心数据库是如何实现的,而只用关心到数据库的连接。ADO涉及的数据存储
有DSN(数据源名称)、ODBC(开放式数据连接)以及OLE DB三种方式。。odbc,oledb这些系统级的编程接口是底层的,操作起来相对困难,
我理解为ADO是对ODBC和OLEDB的封装吧,这样方便开发人员使用。


ODBC与OLEDB:
ODBC和OLE DB都是应用程序接口,都是为了应用程序访问数据库定制的一组标准,而ODBC是曾经的数据库通信标准,而OLE DB是在一切对象
化的趋势下,微软打算用它取代ODBC。由上图可知OLEDB分两种:直接操作数据库的OLEDB和面向ODBC来操作数据库的OLEDB,后者架构在ODBC上
,这样没 有自己的OLEDB提供者的数据库也可以使用OLEDB的特点了。这样看来OLEDB总体上支持的数据库要比ODBC多,至于效率问题,我认
为OLEDB在操作数据库时效率是ODBC快,而通过ODBC这层转换后效率就比ODBC低了。




SQL Server2005中创建数据库student,该数据库中有学生表s用来存放学生信息。s表的结构如下:

属性名

类型

是否为主键

允许空

备注

sno

char(8)

学号

sname

varchar(10)

姓名

age

int

年龄

dept

char(4)

所在系号

comment

varchar(8)

评语

基于ADO方式的实验步骤

此例中所用数据库与上例中相同;

此例中无需创建数据源。

1)创建VC应用程序

 打开VC++6.0,新建工程。选择MFC AppWizardexe),工程名为exec2,存放在D盘实验文件夹里。点击“确定”,在弹出的窗口中选择“基本对话框”,以后的步骤没有需要修改的地方,可以直接点击“完成。”这样一个基于基本对话框的工程就创建好了。

2)界面设计

 在工作区左边的树型结构中,选择ResourceView,展开Dialog节点,双击IDD_EXEC2_DIALOG,打开该对话框。在这里添加所需控件。如图17所示。

17

 为编辑框和列表框添加变量。在界面右键单击,选择“建立类向导”,弹出如图18所示窗口。

18

本例中需要为编辑框IDC_AGE, IDC_COMMENT, IDC_DEPT, IDC_NAME, IDC_SNO,列表框IDC_LIST添加变量。以IDC_AGE为例,点击“ADD Variable”弹出如图19所示窗口。

19

这里变量名为m_age,类型可从下拉框里选。添加变量完成之后类向导如图20所示。

20

 为按钮添加函数,双击按钮可为其添加函数,在exec2Dig.cpp文件里。

3)与ADO相关的代码设计

 引入ADO库文件,使用ADO前必须在工程的StdAfx.h头文件里用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下所示:

//加入ADO支持库

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

//namespace是命名空间,这里不需要命名空间,主要是为了访问方便,在程序中可以直接访问ADO提供的ConnectionCommandRecordset这三个COM接口

 定义ADO连接、命令、记录集变量指针,在exec2Dlg.h文件的class CExec2Dlg : public CDialog方法中添加如下代码:

    // 定义ADO连接、命令、记录集变量指针

_ConnectionPtr m_pConnection;

_CommandPtr m_pCommand;

_RecordsetPtr     m_pRecordset;

// 该指针为整个应用程序共享,所以放在public下面。

 初始化OLE/COM库环境。必须注意的是,ADO库是一组COM动态库,这意味应用程序在调用ADO前,必须初始化OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在应用程序主类的OnInitDialog()成员函数里初始化OLE/COM库环境。

在本例中,在exec2.cpp文件的BOOL CExec2Dlg::OnInitDialog()成员函数里添加如下代码:

//初始化COM,创建ADO连接等操作

AfxOleInit();

m_pConnection.CreateInstance(__uuidof(Connection));

//ADO操作中建议语句中要常用try...catch()来捕获错误信息,

//因为它有时会经常出现一些想不到的错误

try                 

{

//打开本地Sql Serverstudent

        m_pConnection->Open("driver={SQL Server};Server=XP-201203132217\\SQLSERVER2005;Database=Student;UID=sa;PWD=yuzhongchun","","",adModeUnknown);

//Server后是服务器的计算机名,注意XP-201203132217\\SQLSERVER2005是双斜线啊,写错了就会返回 [Microsoft][ODBC SQL Server Driver][DBNETLIB]SQL Server 不存在或访问被拒绝

//Database后是数据库名

// UID="";PWD=""写入相应的用户名和密码,这里使用的是SQL server验证

}

catch(_com_error e)

{

AfxMessageBox("数据库连接失败!");

return FALSE;

 在exec2Dlg.cpp文件中添加代码。

在#endif下面添加如下代码:

 extern CExec2App theApp;       // 在此引用应用类中的theApp来获取库连接指针

在BOOL CExec2Dlg::OnInitDialog()函数中添加如下代码:

// TODO: Add extra initialization here

//使用ADO创建数据库记录集

m_pRecordset.CreateInstance(__uuidof(Recordset));

// ADO操作中建议语句中要常用try...catch()来捕获错误信息,

// 因为它有时会经常出现一些想不到的错误

try

{

m_pRecordset->Open("SELECT * FROM s",                // 查询s表中所有字段

m_pConnection.GetInterfacePtr(),  // 获取库接库的IDispatch指针

adOpenDynamic,

adLockOptimistic,

adCmdText);

}

catch(_com_error *e)

{

AfxMessageBox(e->ErrorMessage());

}

 至此,与ADO相关的代码都已添加完了。下面在exec2Dlg.cpp文件中添加应用代码。

4)与功能相关的代码设计

 在界面上用到列表框,当鼠标点击列表框的某一行时,其中的数据能够在编辑框中显示出来,这要用到列表框的一个函数。添加此函数的方法如下:摁住Ctrlw键,进入类向导,如图21所示。

21

选择IDC_LIST,在右边的Messages下面选择LBN_SELCHANGE,然后点击“Add Function”按钮,最后点击“确定”按钮,即为列表框添加了此函数。具体代码如下:

//名称:OnSelchangeList

//功能:当每次选择新的记录时,都会移动指针到新的记录位置并将值显示出来

void CExec2Dlg::OnSelchangeList() 

{

int curSel = m_list.GetCurSel();

_variant_t var,varIndex;

if(curSel < 0)

return;

try

{

// 先将指针移向第一条记录,然后就可以相对第一条记录来随意移动记录指针

m_pRecordset->MoveFirst();

m_pRecordset->Move(long(curSel));

var = m_pRecordset->GetCollect("sname");

if(var.vt != VT_NULL)

m_sname = (LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("age");

if(var.vt != VT_NULL)

m_age=(LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("sno");

if(var.vt != VT_NULL)

m_sno = (LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("dept");

if(var.vt != VT_NULL)

m_dept = (LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("comment");

if(var.vt != VT_NULL)

m_comment = (LPCSTR)_bstr_t(var);

UpdateData(false);

}

catch(_com_error *e)

{

AfxMessageBox(e->ErrorMessage());

}

}

 将数据库中的数据显示在列表框中,添加函数ListData()。添加的方法是,在工作区左边的树型结构中,选择ClassView,右键单击CExec2Dlg,在弹出的菜单中选择Add Member Function,出现如图22所示的窗口,类型为void,函数描述为ListData()

22

此函数的具体代码如下:

//名称:ListData

//功能:将数据库中的数据显示在列表框中

void CExec2Dlg::ListData()

{

    _variant_t var;

CString strname,strage,strsno,strdept,strcom;

//清空列表框

m_list.ResetContent();

strname=strage=strsno=strdept=strcom="";

//ADO操作中建议语句中要常用try...catch()来捕获错误信息,

//因为它有时会经常出现一些想不到的错误。

try

{

if(!m_pRecordset->BOF)

m_pRecordset->MoveFirst();

else

{

AfxMessageBox("表内数据为空");

return;

}

// 读入库中各字段并加入列表框中

while(!m_pRecordset->adoEOF)

{

var = m_pRecordset->GetCollect("sno");

if(var.vt != VT_NULL)

strsno = (LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("sname");

if(var.vt != VT_NULL)

strname = (LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("age");

if(var.vt != VT_NULL)

strage = (LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("dept");

if(var.vt != VT_NULL)

strdept = (LPCSTR)_bstr_t(var);

var = m_pRecordset->GetCollect("comment");

if(var.vt != VT_NULL)

strcom = (LPCSTR)_bstr_t(var);

m_list.AddString( strsno + " --> " +strname + " --> "+strage+ " --> "+ strdept+ " --> "+ strcom);

m_pRecordset->MoveNext();

}

// 默认列表指向第一项,同时移动记录指针并显示

m_list.SetCurSel(0);

OnSelchangeList();

}

catch(_com_error *e)

{

AfxMessageBox(e->ErrorMessage());

}

}

 插入按钮对应的函数代码如下:

//名称:OnWritedata

//功能:将编辑框中输入的学生信息插入到s表中

void CExec2Dlg::OnWritedata() 

{

UpdateData();

if(m_sname == "" || m_sno == "")

{

AfxMessageBox("学号和姓名信息不能为空!");

return;

}

//ADO操作中建议语句中要常用try...catch()来捕获错误信息,

//因为它有时会经常出现一些想不到的错误。

try

{

// 写入各字段值

m_pRecordset->AddNew();

m_pRecordset->PutCollect("sno", _variant_t(m_sno));

m_pRecordset->PutCollect("sname", _variant_t(m_sname));

m_pRecordset->PutCollect("age", atol(m_age));

m_pRecordset->PutCollect("dept", _variant_t(m_dept));

m_pRecordset->PutCollect("comment", _variant_t(m_comment));

m_pRecordset->Update();

AfxMessageBox("插入成功!");

// 更新显示其库内容

int nCurSel = m_list.GetCurSel();

ListData();

m_list.SetCurSel(nCurSel);

// 移动记录指针到新的位置

OnSelchangeList();

}

catch(_com_error *e)

{

AfxMessageBox(e->ErrorMessage());

}

}

 修改按钮对应的函数代码如下:

//名称:OnModify

//功能:修改学生信息

void CExec2Dlg::OnModify() 

{

UpdateData();        // 更新对话框数据

if(m_list.GetCount() == 0)

{

AfxMessageBox("表中记录数为空!");

return;

}

else if(m_list.GetCurSel() < 0 || m_list.GetCurSel() > m_list.GetCount())

m_list.SetCurSel(0);

// 修改当前记录的字段值

try

{

m_pRecordset->PutCollect("sno", _variant_t(m_sno));

m_pRecordset->PutCollect("sname", _variant_t(m_sname));

m_pRecordset->PutCollect("age", atol(m_age));

m_pRecordset->PutCollect("dept", _variant_t(m_dept));

m_pRecordset->PutCollect("comment", _variant_t(m_comment));

m_pRecordset->Update();

// 重新读入库记录更新显示

int nCurSel = m_list.GetCurSel();

ListData();

m_list.SetCurSel(nCurSel);

// 移动记录指针到新的位置

OnSelchangeList();

}

catch(_com_error *e)

{

AfxMessageBox(e->ErrorMessage());

}

}

 删除按钮对应的函数代码如下:

//名称:OnDelete

//功能:删除选中的学生信息

void CExec2Dlg::OnDelete() 

{

    if(m_list.GetCount() == 0)

return;

else if(m_list.GetCurSel() < 0 || m_list.GetCurSel() > m_list.GetCount())

m_list.SetCurSel(0);

try

{

// 删除当前行记录

m_pRecordset->Delete(adAffectCurrent);

m_pRecordset->Update();

// 删除列表中当前值

int nCurSel = m_list.GetCurSel();

m_list.DeleteString(nCurSel);

if(nCurSel == 0 && (m_list.GetCount() != 0))

m_list.SetCurSel(nCurSel);

else if(m_list.GetCount() != 0)

m_list.SetCurSel(nCurSel-1);

// 移动记录指针到新的位置

OnSelchangeList();

}

catch(_com_error *e)

{

AfxMessageBox(e->ErrorMessage());

}

}

 查询按钮对应的函数代码如下:

//名称:OnQuery() 

//功能:按照学号和姓名查询学生信息,如果只输入学号则只按照学号查询

//只输入姓名则只按照姓名查询,两者都没有输入则查询所有学生信息

void CExec2Dlg::OnQuery() 

{

    UpdateData(TRUE);

//构造Sql语句

//为简单考虑,这里只把学号和姓名作为查询条件

CString strSql;

if(m_sname != "" && m_sno != "")

strSql.Format("SELECT * FROM s WHERE sname = '%s' AND sno = '%s'",

m_sname,m_sno);

else if(m_sname != "" && m_sno == "")

strSql.Format("SELECT * FROM s WHERE sname = '%s'",m_sname);

else if(m_sname == "" && m_sno != "")

strSql.Format("SELECT * FROM s WHERE sno = '%s'",m_sno);

else

strSql = "SELECT * FROM s";

try

{

//先关闭已经打开的记录集对象

m_pRecordset->Close();

//根据新的Sql查询语句,重新打开记录集对象

m_pRecordset->Open(strSql.AllocSysString(),                

   theApp.m_pConnection.GetInterfacePtr(),

   adOpenDynamic,

   adLockOptimistic,

   adCmdText);

}

catch(_com_error *e)

{

AfxMessageBox(e->ErrorMessage());

}

//将查询后得到的新记录集显示出来

ListData();

}

 刷新按钮对应的函数代码如下:

//名称:OnRefresh

//功能:刷新编辑框和列表框

void CExec2Dlg::OnRefresh() 

{

m_sno="";

m_sname="";

m_age="";

m_dept="";

m_comment="";

m_list.ResetContent();

UpdateData(false);

}

5)运行结果



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

智能推荐

DP mixture model-程序员宅基地

文章浏览阅读65次。http://people.csail.mit.edu/jacobe/software.html转载于:https://www.cnblogs.com/stoneresearch/archive/2011/09/03/4336539.html_dpmm饭圈

Python对Linux系统的操作,打开文件与读写文件,python模拟linux的cp操作_python读取linux文件-程序员宅基地

文章浏览阅读1.1w次。cp操作请跳到第10节1.open内建打开文件函数作为打开文件的“钥匙”,内建函数open()提供了初始化输入/输出(I/O)操作的通用结接口成功打开文件后会返回一个文件对象,如果打开失败会引发一个错误示例:file_object = open(file_name,mode='r')file_object 是python的变量名用来保存文件对象mode是打开的方式,以读..._python读取linux文件

Celo中的随机数_uint(keccak256(abi.encodepacked(blockhash(block.nu-程序员宅基地

文章浏览阅读208次。1. 引言在无需可信第三方的情况下,实现不可预测的伪随机数的方案有:VRFVDFCommit-reveal当前,Celo项目采用的是简单的commit-reveal方案来随机选择Validator.对于某特定Validator propose的第nnn个区块,该Validator会在该区块内附加值(rn,sn)(r_n,s_n)(rn​,sn​),使得keccak256(rn)=sn−1\text{keccak256}(r_n)=s_{n-1}keccak256(rn​)=sn−1​。对于_uint(keccak256(abi.encodepacked(blockhash(block.number - 1), gasleft())))

HTML的层级_html怎么调层级-程序员宅基地

文章浏览阅读1.4k次。在网页中,对于已经开启定位的元素可以设置元素层级,如果定位的元素层级是一样的, 下边的元素会盖住上边,在定位的情况下,通过z-index属性设置元素的层级,属性值:是一个正整数,层级越高,优先级也就越高 .box{ width: 200px; height: 200px; } .box1{ background-color: rebeccapurple; position:relative; _html怎么调层级

数据标签化:如何通过标签化数据进行文本分类和自然语言处理自然语言处理教程_简易自然语言处理标签化-程序员宅基地

文章浏览阅读2.8k次。在自然语言处理中,词性标注、命名实体识别、句法分析、语义理解、语音合成、信息检索、文档摘要等功能需要对输入文本进行分析处理。这些任务通常都涉及到大量的数据处理工作。例如,给定一个文本序列(如一段话或一篇文章),如何自动地确定其中的名词短语、动词短语、介词短语、形容词短语?这个过程被称之为词性标注。再比如,给定一段文本,如何识别出其中的人物、组织机构、地点、时间、日期、货币金额等实体?这个过程被称之为命名实体识别。每当我们阅读、回复、输入文字时,都离不开这些功能,它们的背后都是复杂的计算过程。_简易自然语言处理标签化

数据结构与实验报告二—— 链表的基本操作及应用(图书管理系统)_数据结构链表实验报告-程序员宅基地

文章浏览阅读8k次,点赞4次,收藏72次。第一章实验目的1.掌握线性表的链式存储结构的表示和实现方法。2.掌握单链表基本操作的算法实现。3.了解单链表的应用。第二章 实验环境硬件环境要求:PC机(单机)使用的软件名称、版本号以及模块:DEV C++、VS2010等。第三章 实验内容1.编写一个程序,实现单链表的各种基本运算(假设单链表的元素类型为char),并在此基础上设计一个主程序完成如下功能:(1)初始化单链表h;(2)依次采用尾插法插入a、b、c、d、e元素;(3)输出单链表h;(4)输出单链表h的长度;(5)判_数据结构链表实验报告

随便推点

【Python搜索算法】广度优先搜索(BFS)算法原理详解与应用,示例+代码_python bfs-程序员宅基地

文章浏览阅读5k次,点赞24次,收藏68次。广度优先搜索(Breadth-First Search,BFS)是一种图遍历算法,用于系统地遍历或搜索图(或树)中的所有节点。BFS的核心思想是从起始节点开始,首先访问其所有相邻节点,然后逐层向外扩展,逐一访问相邻节点的相邻节点,以此类推。这意味着BFS会优先探索距离起始节点最近的节点,然后再逐渐扩展到距离更远的节点。BFS通常用于查找最短路径、解决迷宫问题、检测图是否连通以及广泛的图问题。BFS算法的步骤如下:初始化:选择一个起始节点,将其标记为已访问,并将其放入队列中(作为起始节点)。_python bfs

cpickle支持的python版本_Python序列化模块pickle和cPickle-程序员宅基地

文章浏览阅读113次。Python的序列化是指把变量从内存中变为可以储存/传输的数据/文件的过程. 在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。在Pytho..._cpickle.dump(obj, f, protocol)

Stream.generate-程序员宅基地

文章浏览阅读3.1k次。static<T>Stream<T>generate​(Supplier<? extends T>s)该方法主要用于生成一个无限连续的无序流,流中的元素由用户定义的supplier函数生成。看个简单例子:运行结果:aa该方法一般配合limit方法使用,在这个例子中我们使用limit方法限制这个无限流的长度为2,因此最终打印出两个a。加入我们不使用limit方法限制流长度会出现什么情况?测试一下。Stream<String> ..._stream.generate

tmux分屏解决方案_tmux的分窗口分不了-程序员宅基地

文章浏览阅读326次。安装使用个人推荐方案(自定义按键)先ctrl+a,再输入命令 - u/i : 创建水平/竖直新窗口 - o : tab - h/j/k/l : 更改当前窗口大小_tmux的分窗口分不了

json文件的格式转换_json格式转换-程序员宅基地

文章浏览阅读4.8k次。温故而知新。_json格式转换

使用gradle build项目报错:Main class name has not been configured and it could not 问题处理-程序员宅基地

文章浏览阅读1.8w次,点赞3次,收藏4次。Execution failed for task ‘:api:bootJar’.> Main class name has not been configured and it could not这里记录一个Bug处理:Task :api:bootJar FAILEDFAILURE: Build failed with an exception.What went wrong:Execution failed for task ‘:api:bootJar’.Main clas_main class name has not been configured and it could not be resolved

推荐文章

热门文章

相关标签