摘要:本文分析现有的数据库访问中间件的现状,指出其中存在的问题,得出应用新技术的必要性。开发了一个基于web服务技术的数据库访问中间件wsdbm,并以一个应用实例验证了该中间件的有效性。
关键词:web服务;数据库访问中间件;.net
1 引言
随着intranet/internet网络的迅猛发展,面向网络的分布式数据库成为支持internet服务的关键,传统的数据库访问技术已渐渐不能满足分布式应用集成的需要。
【1】利用新技术,研究和开发新的数据库访问中间件成为数据库研究领域的主要方向之一。
web服务是一种崭新的分布式计算模型,基于一系列开放的技术标准,其松散耦合、语言中立、平台无关性、开放性使得它将成为下一代电子商务的架构,成为下一代的www。
【2】microsoft.net提供了基于“.net框架”的综合开发平台,它提供了涉及客户端、服务器和服务的单独、统一的编程模型。
“.net框架”和visual studio.net一起,给我们提供了一个完整的应用程序开发平台。
本文主要的工作就是在visual studio.net平台上,利用web服务将现有的数据库访问方式的封装成中间件,使得封装后的中间件可以满足分布式应用的需要。
2 web服务中间件接口的定义
现有通用的数据库访问方式,它的主要操作有:设置数据库连接,打开和关闭数据库, 执行查询和执行其他的sql语句,实现事务管理和缓冲池管理。比较先进的数据库访问方式还支持实时数据库连接。因此,为了实现对传统数据库访问方式的封装,我们首先要定义一个web服务,这个web服务至少应该拥有以上所列的web方法(属性为webmethod的public函数成员)。这些方法就组成了这个web服务的接口。
.net下,web服务的实现都封装在system.web.services.webservice这个类中。为了实现对数据库访问方式的web服务的封装,我们必须定义一个新的类,它继承于webservice或是它的子类。对于相对简单的web服务,我们直接让这个类继承于webservice。这个生成的类就成了一个具体的web服务。
.net中新的关系型数据管理类都是基于类库中system.data的一系列的名称空间,通常称这些名称空间集合为ado.net。system . data包含用来访问和存储关系型数据的基础对象。visual studio.net直接给我们提供了system.data.sqlclient和oledbclient两个命名空间,这两个命名空间分别包含有用来访问sql server关系数据库和其他关系数据库所需的基本对象。其中以transaction结尾的类提供了事务管理的功能,以connection结尾的类用于连接具体的数据库。以command结尾的类定义了对数据库表的操作。
3 web服务中间件的实现
3.1实现框架
下面是一个简单的web服务中间件来实现(采用microsoft推荐的c #语言来编写)。为了实现中间件的可扩展性,我们决定不在中间件的webmethod(web方法)中直接实现对数据库的操作。我们先定义一个虚类dboperator,在这个虚类中定义了对数据库操作的接口,包括数据库的打开(open)和关闭(close),事务的开始(begintrans)、事务的递交(committrans)和回滚(rollbacktrans),没有返回值的sql语句的执行(void execsql)和返回数据集的sql语句的执行(dataset execsql)。这样,我们的web服务中间件的每个webmethod就仅仅是调用了dboperator对象的相应的成员函数。比如web服务中间件中的open方法就是直接调用dboperator对象的open方法。
3 .2具体数据库操作的实现
为了具体实现对数据库的操作,我们需要定义dboperator类的子类,我们以sqldboperator为例,显然sqldboperator具体实现了对sql server数据库的操作。
首先定义一个sqldboperator类,它继承于dboperator,并导入名称空间system . data . sqlclient。
using system.data.sqlclient;
class sqldboperator:dboperator
其次添加私有的数据成员conn,trans,intransaction,comm
private sqlconnection conn; //数据库连接
private sqltransaction trans; //事务处理类
private bool intransaction=false; //指示当前是否正处于事务中
private sqlcommand comm; //数据库操作命令处理类
然后我们开始编写从dboperator继承下来的open操作的实现语句。
public override void open(string connstr)
{
//如果连接是空的,就先通过connstr构造一个连接
if(conn==null)
conn=sqlconnection(connstr);
//如果这个连接没有打开,就打开这个连接
if(conn.state.tostring().toupper()!="open")
this.conn.open();
}
在实现了open(打开数据库)操作的编写之后,我们开始编写close(关闭数据库)操作。
public override void close()
{
//如果连接是空的,则不用关闭
if(conn==null)
return;
//如果这个连接已经打开,就关闭这个连接
if(conn.state.tostring().toupper()=="open")
this.conn.close();
}
事务处理功能的实现:首先是begintrans(开始事务)操作的实现。
public override void begintrans()
{
//如果连接是空的,则没有事务可以开始
if(conn==null)
return;
/*开始conn所属的事务,并将这个事务保存下来,同时设置intransaction(在事务中)标志为true(真)。表示在进行事务处理*/
trans=conn.begintransaction() ;
intransaction=true;
}
接下来是committrans(递交事务)操作的实现如下:
public override void committrans()
{
trans.commit(); //事务递交
intransaction=false;//在事务中标志变成false;
}
同理,rollbacktrans(回滚事务)操作的实现如下:
public override void rollbacktrans ()
{
trans.rollback(); //事务回滚
intransaction=false;//在事务中标志变成false;
}
最后我们编写execsql(执行sql语句)操作的实现:
public override void exesql(string strsql,string[] strparams,object[] strvalues)
{
//如果comm(处理sql语句的对象)为空,则生成这个对象
if(comm==null)
comm=new sqlcommand();
//设置这个对象的连接conn
comm.connection=this.conn ;
//判断是否在事务中,是就设置comm的事务对象属性
if(intransaction)
comm.transaction=trans;
//判断参数个数和参数值个数是否相等,不等,就不能执行这个sql语句
if((strparams!=null)&&(strparams.length!=strvalues.length) )
throw new exception("查询参数和值不对应!");
//设置这个comm对象的命令文本
comm.commandtext=strsql;
//将参数名称和对应的参数值保存到comm的参数数组中
if(strparams!=null)
{
for(int i=0;i<strparams.length;comm.parameters.add(strparams[i],strvalues[i]));
}
//执行这个没有返回值的查询
comm.executenonquery();
}
下面是有返回值的execsql操作的实现:
public override dataset exesqlfordataset(string querystring)
{
//如果comm(处理sql语句的对象)为空,则生成这个对象
if(comm==null)
comm=new sqlcommand();
//设置这个对象的连接conn
comm.connection=this.conn ;
//判断是否在事务中,就是设置comm的事务对象属性
if(intransaction)
comm.transaction=trans;
//生成一个数据集(dataset)对象(ds),用它来保存返回的查询结果
dataset ds = new dataset();
//定义一个sqldataadpater类的对象ad。
sqldataadapter ad = new sqldataadapter();
//设置这个comm对象的命令文本
comm.commandtext=querystring;
//设置ad的selectcommand属性为comm。
//selectcommand是dataadapter对象的一个属性,表示transact-sql语句或存储过程,用于在数据源中选择记录。
ad.selectcommand =comm;
//ad执行fill操作,结果保存到ds中
ad.fill(ds);
//ds返回
return ds;
}
4 使用已定义的web服务中间件来访问数据库的使用场合
下面我们假设一种该中间件使用的具体情况:
假设有一个私有的比较大型的书店,书店的老板家在离书店有一段距离,在书店和老板家之间架设局域网是不现实的,而老板需要在家里就可以使用书店的管理系统,甚至进行日常工作的管理。也就是说,老板需要实现在家里办公。为此,书店老板决定让某it公司开发这个系统。
某it公司在接到该书店老板提出的开发意向后,在进行初步的系统调研之后,决定接下这个it订单,由于这个书店老板并没有提出具体的解决方案(他也不懂),所以it公司人员思考了以下几个开发方案:
在传统的解决方案中,我们可以采用了动态网页的编程方法,也就是建立一个网站,这样,在互联网的任何地方,我都可以通过这个网站进行访问,这种实现方法非常优秀,现有的很多公司门户就是使用了这种技术实现的。但是这种技术有一个缺点是,书店需要有自己的web服务,这就增加了实现成本。同时这种方案的实现也抛弃了现有的解决方案(书店在建立初期就请某it公司专门开发一个专用的书店管理系统),抛弃这个legacy(遗产),重新进行设计,书店老板也不愿意。
另一个传统的解决方案是利用corba或dcom进行编程。原有系统就是利用visual c++进行编程的。所以可以选择dcom进行编程,这也非常合理。但是这个方案限制了实现的平台,同时开发费用较高,毕竟利用dcom进行编程开发和实现是一件比较复杂的工作。
最后,公司决定利用web服务技术封装原有的数据库访问层,这样我们的客户端仅需要进行数据库访问层的修改。这样,系统原来的界面不便,business层(业务层)不变,改变的仅仅是客户端的的数据库访问层的实现。以上就是这个web服务使用的具体场合。
下面我们在visual studio.net平台上利用c# windows应用程序编程项目来说明该web服务的使用。
首先新建一个c# windows应用程序项目,在窗体上添加控件,一个datagrid和一个按钮。
然后添加web引用,将该web服务中间件所在的asmx文件地址添加到web引用中。这样我们就可以直接使用这个服务了。
双击按钮1,编程如下:
//新建一个web服务的实例
webreference.servicewsdbm the=new windowsapplication1.webreference.servicewsdbm();
//以数据库连接字符串为参数,打开上面的连接字符串所可以连接的数据库
the.open("provider=sqloledb.1;persist security info=false;user id=sa;initial catalog=northwind;use procedure for prepare=1;auto translate=true;packet size=4096;use encryption for data=false;tag with column collation when possible=false");
the.open();
//对已经打开的数据库进行查询操作,返回记录集。
system.data.dataset ds=the.exesqlfordataset("select * from products");
//将查询得到的记录集显示在datagrid中
datagrid1.datasource=ds;
datagrid1.datamember=ds.tables[0].tablename;
//关闭这个连接
the.close();
执行结果,在datagrid中将显示出连接上的sql server库中的products表中的内容。
5 结束语
根据以上的介绍,基于web服务实现的数据库访问中间件,可以扩展数据库系统的应用范围,这种中间件不仅适应于局域网,更加适应于未来的基于广域网的应用程序。这个中间件于传统中间件相比有以下优点: 1)跨平台。2)使用方便,可以将这个web服务可以象本地组件一样被应用。3)兼容性强,扩展方便,比如我们想要增加对oracle的支持,仅需下载和oracle有关的.net插件(下载地址:可到http://msdn.microsoft.com/downloads/上下载.net framework data provider for oracle),然后将上述程序中的sql替换为oracle即可。综上所述,基于web服务实现数据库访问中间件将是一种比较有效的解决方案。
新闻热点
疑难解答