实战案例使用ADO和三层架构完成登录实例资料文档格式.docx
- 文档编号:22930478
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:24
- 大小:220.70KB
实战案例使用ADO和三层架构完成登录实例资料文档格式.docx
《实战案例使用ADO和三层架构完成登录实例资料文档格式.docx》由会员分享,可在线阅读,更多相关《实战案例使用ADO和三层架构完成登录实例资料文档格式.docx(24页珍藏版)》请在冰豆网上搜索。
为了防止用户名有重复,我们规定用户名作为主键(作为主键的列不能为空,且值要唯一)。
同时为了防止非授权的用户登录软件(例如盗用密码或者清除密码),我们规定每个用户的密码文件不能够为空。
表格效果如下图:
建立数据库和数据表的代码如下:
createdatabaseTest--创建名称为Test的数据库
go
useTest--使用该数据库
createtableLogin_inf--创建登录信息表
(
UserNamevarchar(20)primarykey,--创建用户名列,为主键
PasswordKeyvarchar(20)notnull,--创建密码列,要求该列单元格添加数据不能为空值
)
insertintoLogin_infvalues('
jianghanxin'
'
jiang_1994221'
)--添加一个元组
运行之后在SQLServerManagementStudio的“对象资源管理器”中可以查看到我们所建立的数据库Test和数据表Login_inf。
如下图:
【第一步:
从数据库访问层开始】
接下来我们设计完成数据库之后我们可以开始对C++代码的设计。
首先我们从最基本的也是最底层的数据库访问层开始。
由于我们所有的操作都是要通过数据库访问层执行SQL语句完成的,因此数据库访问层我们可以这样描述。
数据库访问层用于和数据库打交道,用于将应用程序和SQLServer数据库建立连接,并且执行相应的数据操作。
如果有类似于查询的返回结果,则返回带有查询结果的记录集。
在完成数据库操作之后我们可以关闭数据库连接。
小提示:
每次执行数据库操作都必须要先打开数据库连接,完成操作之后,再将数据库连接关闭。
否则程序将会报错。
在了解了上述的功能描述后我们可以建立一个类描述数据库访问层,例如DataBase。
声明的代码如下:
#pragmaonce
#ifndefDATABASE_H
#defineDATABASE_H
#include<
iostream>
afx.h>
comdef.h>
conio.h>
#import"
C:
\ProgramFiles\CommonFiles\System\ado\msado15.dll"
no_namespacerename("
EOF"
"
adoEOF"
usingnamespacestd;
classDataBase
{
public:
DataBase(_bstr_tDataBaseName);
~DataBase(void);
intExcute(_bstr_tconst&
CommandString);
//执行非查询的数据库命令
_RecordsetPtr&
ExcuteSelect(_bstr_tconst&
//执行查询的数据库命令
voidOpen();
//打开数据库连接
voidClose();
//关闭数据库连接
private:
_ConnectionPtrMyConnection;
//数据库连接指针
_RecordsetPtrRecords;
//数据库记录集指针
_bstr_tConnectionString;
//连接字符串
};
#endif
DataBase函数:
DataBase函数是该类的构造函数,通常构造函数负责一些初始化的工作。
为了能够减少后期我们工作的麻烦,例如每次调用DataBase类都需要获取数据库字符串。
为了大家能够更好的理解数据库的连接字符串,我们在这里不妨对数据库的连接字符串进行一些分析。
有如下的连接字符串:
Provider=SQLOLEDB.1;
IntegratedSecurity=SSPI;
PersistSecurityInfo=False;
InitialCatalog=Test;
DataSource=(local)
其中Provider参数说明连接数据库所使用的驱动引擎,由于我们使用的是ADO技术,故此我们使用的SQLOLEDB.1驱动。
我们可以通过打开.udl文件,并且点击“提供程序”选项卡进行选择。
此处我们可以看到所选择的是“MicorosoftOLEDBProviderforSQLServer”,其含义相信大家都能够明白吧!
当然,此处我需要再次解释一下ADO其实是对OLEDB访问技术的又一次封装,使得我们访问数据库变得更加的简单,因此说到底ADO技术的本质其实还是OLEDB。
因此我们在选择提供程序时应该选择MicorosoftOLEDBProvider,由于我们使用的数据库为SQLServer,因此我们需要选择的是forSQLServer。
接下来我们需要知道的是“InitialCatalog”参数,该参数用于描述应用程序究竟应该访问哪一个数据库,其后的等于号跟的是应用程序需要访问的数据库的名称,即Test。
另外我们还需要了解“DataScource”参数,该参数用于描述数据源,即数据库服务器的地址,由于我们的电脑上已经安装了SQLServer2008,此时我们的电脑也可以作为一个单独的数据库服务器,名称为(local)或者localhost。
上述的两个参数我们可以打开udl文件在“连接”选项卡中查看。
为了我们每次编程的时候不需要去通过udl文件获取连接字符串,我们可以通过字符串的连接将连接字符串进行相应的处理。
由于我们此时需要操作的信息基本固定,除了每次所访问的数据库不同,因此我们只需要修改“InitialCatalog”参数后的值就可以了。
代码如下:
this->
ConnectionString="
UserID=sa;
InitialCatalog="
;
ConnectionString+=DataBaseName;
//将该变量的参数与InitialCatalog连接
ConnectionString+="
DataSource=(local)"
接下来我们还需要在构造函数中完成一件很重要的事情——初始化COM环境。
由于ADO也是COM组件,因此我们使用ADO之前都需要初始化COM组件,为了能够完成自动初始化环境,我们可以将初始化的代码放置到构造函数中(构造函数在创建对象时自动执行)。
初始化COM组件的代码如下:
//初始化COM编程环境
if(FAILED(:
:
CoInitialize(NULL)))
cout<
<
"
初始化COM环境失败!
endl;
_getch();
return;
}
大致来说构造函数中所要完成的事情都是一些琐碎的细枝末节,例如对于类中属性的初始化,以及对于环境的初始化等。
这些细枝末节通常是很多人都容易忘记的,也通常不在我们描述程序的范围之内,毕竟客户不需要知道这些技术细节,因此我们需要在构造函数中完成它们,让构造函数每次新建对象之时自动为我们进行初始化操作。
DataBase类的完整代码如下:
DataBase:
DataBase(_bstr_tDataBaseName)
this->
MyConnection=NULL;
//设置连接指针为空,防止野指针
Records=NULL;
//设置记录集指针为空,防止野指针
//设定连接字符串,需要连接的数据库通过构造函数的形参指定
//初始化COM编程环境
if(FAILED(:
{
cout<
_getch();
//使用C++标准的getch函数
return;
}
~DataBase函数:
~DataBase函数是DataBase类的析构函数,析构函数主要负责退出COM环境,以免每次新建对象时初始化环境失败。
析构函数代码如下:
~DataBase(void)
:
CoUninitialize();
//退出COM环境
Open函数:
Open函数是DataBase类中由程序员所创建,负责创建连接对象,设定连接参数,并且打开数据库连接。
voidDataBase:
Open()
try
MyConnection.CreateInstance(_uuidof(Connection));
//创建连接对象
MyConnection->
ConnectionString=this->
ConnectionString;
//指定连接字符串
ConnectionTimeout=10;
//指定连接超时为10s
do
{
MyConnection->
Open("
adConnectUnspecified);
//打开连接
}
while(MyConnection->
State!
=adStateOpen);
catch(_com_errore){}
其中try{}catch(_com_errore){}用于检测该代码是否会产生异常情况使得程序崩溃。
这一步是很有必要的。
当然我们在此设定只要连接状态处于关闭状态,就不断地向数据库使用MyConnection->
Open函数不断的对数据库进行连接,直到连接上数据库为止。
Close函数:
Close函数负责关闭数据库连接,为了能够提高数据库访问层的效率,我们可以先判断MyConnection中的State属性,如果处于打开状态(adStateOpen)则调用Close函数,关闭数据库连接。
Close()
if(MyConnection->
State==adStateOpen)//如果连接处于打开状态
Close();
Excute函数:
对数据库的操作通常分为查询操作和非查询操作,非查询操作包括INSERT(插入)、UPDATE(更新)、DELETE(删除),Excute函数用于执行非查询操作的SQL语句,由于SQL语句的变数还是很多的,因此我们可以将SQL语句作为Excute函数的形参。
为了能够检测SQL语句是否执行成功,我们可以通过返回一个int类型的值(其含义为影响多少行)。
整体结构如下:
intDataBase:
Excute(_bstr_tconst&
CommandString)
此处我们将形参设定为const,防止程序员在使用CommandString参数时不小心改动了这个参数,而使用引用的目的则是为了节省该函数所占用的计算机内存。
如果我们直接使用值传递,则函数会在实参之外另外建立一个内存空间保存CommandString的值。
“浪费空间”这种事情对于一些配置较老的电脑来说是万万不能做的。
毕竟内存的容量还是有限的,不可能所有的内存都给你使用。
Excute函数的代码如下所示:
_variant_tRecordsAffected;
//记录影响的行数
this->
Open();
MyConnection->
CommandTimeout=10;
//设置命令失败延时为10s
Execute(CommandString,&
RecordsAffected,adCmdText);
//执行数据库命令
return(int)RecordsAffected;
//返回影响行数
在此我们使用了刚刚已经在类中定义好的Open函数和Close函数负责打开和关闭数据库连接。
这样我们可以通过函数将代码封装起来,避免了重复写代码的麻烦。
ExcuteSelect函数:
ExcuteSelect函数用于执行查询的操作,通常查询的过程是通过MyConnection中的Excute函数执行SQL语句,并且接收该函数返回的记录集指针(类型为_RecordSetPtr)。
接收完成之后我们可以将该记录集的指针作为返回值返回。
_RecordsetPtr&
DataBase:
ExcuteSelect(_bstr_tconst&
Records.CreateInstance(_uuidof(Recordset));
//创建数据集
Records=MyConnection->
if(this->
Records!
=NULL)
returnRecords;
catch(_com_errore){}//忽略异常
至此,数据库访问的构建结束,最底层的工作也已经做好了。
让我们来看看完整的DataBase类的代码吧!
DataBase.h的内容如下:
DataBase.cpp的内容如下:
#include"
DataBase.h"
catch(_com_errore)
错误原因:
e.ErrorMessage()<
【第二步:
借助数据库访问层完成任务的事务层】
接下来我们需要构造的是事务层,事务层我们也使用一个类进行描述,例如“Kernel”。
事务层的函数通过调用数据库访问层中的函数对数据库进行访问,而数据库访问层如何具体访问数据库的细节,事务层并不需要理会。
本案例中的事务层只有一个功能,就是通过数据库访问层的ExcuteSelect函数查找数据库中是否有符合条件的记录,然后将所得到的结果通过记录集返回到事务层,事务层再通过对记录集的“拆包”,取出返回的数据,并通过该
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实战 案例 使用 ADO 三层 架构 完成 登录 实例 资料