天天看点

Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)

我们整个实例是以一个客户表T_Customer为例进行讲解的,整个表的框架支持代码,可以通过代码生成工具进行快速生成,生成后包括了IDAL、Entity、DALSQL、BLL层代码,然后可以利用代码进行测试存储过程是否执行成功等功能。

数据访问层的定义,依照框架的分层模式来处理,后面我们在增加DALOracle对Oracle数据库进行支持即可。

生成后数据访问层接口,他们通过基类接口继承的方式,已经具有了常规的增删改查、分页等系列接口,但是其他业务接口还是需要自己定义的,如数据访问接口成的定义如下所示。

这里面的代码很简单,没有多余的代码行,那么里面究竟发生了什么呢,其中的IBaseDAL又是什么定义呢?

Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)

其实,IBaseDAL就是定义了很多我们开发用到的基础接口,如标准的增删改查,以及衍生出来的一些其他接口,如分页查询,条件查询等接口内容。这个ICustomer就是用来定义一些除了标准接口不能实现外的业务接口。

如果我们需要实现基于存储过程的接口,我们可能就需要增加一些接口定义,如下所示。

对于插入、更新和删除这样的操作,我们只需要返回它是否成功就可以了,那么它的接口实现应该是如何的呢?

由于我们的Winform开发框架底层是利用微软企业库EnterpriseLibrary来访问数据的,那么对应这个企业库的使用存储过程的方法,也就是我们的实现了。

下面的代码就是它们对应的SqlServer实现了。

对于有返回输出参数的值,我们的做法有些不同,不过最主要的还是最终获取它的输出参数值而已,代码如下所示。

上面的代码,主要就是利用了AddOutParameter对输出参数的信息进行设置,输出参数的数据类型要和脚本里面的类型定义对应,它的AddOutParameter的size参数值,可以为0。

最后我们通过db.GetParameterValue(command, "@MaxAge")的方式获取它的输出参数的值,并返回即可。

最后一个例子是介绍如何通过代码调用,获得它的实体对象或者实体对象列表,以及DataTable集合对象的例子了,这个也相对不是很麻烦,参照框架里面的做法即可。

获取实体对象信息的代码如下所示。

获取集合的代码如下所示。

上面是基于SqlServer存储过程的调用,前面的一篇文章我们介绍了存储过程的Oracle定义,是增加了一个游标来进行记录行数据的处理的,不管对于单行记录,还是多行记录,都是用了游标的输出参数的,那么在客户端里面,使用EnterpriseLibrary,应该如何调用,并且不需要传入这个输出参数的呢,做法其实很类似,只是有一点差异而已。

我们先从最简单的Oracle存储过程调用案例开始,介绍如何调用插入、更新和删除操作的Oracle存储过程的调用。这里和SqlServer的类似,不同的是我们使用了p_前缀来定义参数(基于Oracle的通用脚本参数定义规则)。

Oracle输出外部参数的做法也和sqlServer类似,具体调用代码如下所示。

其他的也就很类似,就不再一一赘述了,基本上和SqlServer的一致,我们节省篇幅,用来看看如何调用返回记录的查询接口。下面是对应的Oracle存储过程的调用代码

返回多条记录的操作代码如下所示。

看完上面两个对记录处理的接口,我们看到,还是对我们在Oracle存储过程里面定义的输出游标参数忽略处理,我们不需要对它进行传值,它好像是透明的,呵呵。

这样它的做法就和SqlServer个各个接口实现也都差不多的了。

下面的脚本是我们之前定义的Oracle存储过程脚本,方便对比参照一下调用的函数代码。

上面我们定义了数据访问接口,以及两种数据实现层,在框架里面会根据不同的数据库类型配置,然后从不同的数据库访问层构建对象的,业务逻辑层主要就是对他们的接口进行调用了,具体代码如下所示。

为了验证我们的实现是否能够正常处理,并顺利获取对应的对象或者集合,我们需要编写一些代码,用来对它进行测试。

测试的代码如下所示。

为了对他们进行测试,我们需要分别对SqlServer和Oracle进行测试,然后才能确认我们的实现是正确的。

分别在SQLServer和Oracle上运行存储过程脚本,创建对应的数据库脚本,如下所示。

Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)
Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)

测试Winform小程序,会得到成功的标志,标识所有的断言全部通过。

Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)

本来写到上面小节,应该就可以告一段落了,因为功能也已经完成了,而且还是支持了两种不同的数据库,说明我们的实现和原先的想法都是正确的。

但是,我从来不喜欢臃肿的代码,我们留心回头看看前面的代码,两种不同数据库的实现很多是相似的,即使对于同一个数据库(如SQLServer)的存储过程接口实现,他们还是有很多优化的地方,代码依旧不够精简和优化,本小节就是专门针对这些进行提炼和优化的。

前面的框架介绍文章,我们可以了解到,数据访问接口实现层和接口定义层一样,都有一个基类,如基于SqlServer实现的基类为BaseDALSQL,这个基于SqlServer的数据访问基类,它也是继承自一个超级基类(大多数的实现在这里)AbstractBaseDAL。他们之间的继承关系如下所示,最终我们把提炼好的内容,放到这个AbstractBaseDAL就可以了,这样各个子类都可以进行调用,实现存储过程的处理。

Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)

对于存储过程的实现,我们分析一下各个接口,可以看到,输入参数是可选的,因为有些接口不需要输出参数;输出参数也是可选的,有些接口也不需要输出参数,返回的记录类型主要有bool类型,实体类型,实体集合类型,DataTable类型这几种,当然虽然有年龄接口的整形,但是这个是通过输出参数来获得的。

我们于是可以定义一个类似这样的通用接口参数集合,用来处理需要返回是否成功获取带有输出参数的,事务对象的接口,如下所示。

它的实现基本上就是分为了几部分,第一部分是传入参数值(包括输入参数、输出参数的值),第二部是执行存储过程,三部分是获得输出参数并修改值即可。

具体的实现代码如下所示。

上面两部分红色哪里,因为他们在很多其他函数里面也通用,所以我就抽离作为一个私有函数了,就是传入参数,和传出结果的两部分。

由于输入输出参数都是可选的,因为我们不确定它是否存在值,所以我们分别对它进行了一定的处理,具体两个函数的代码如下所示。

这样我们就完成了一个普通存储过程该接口的通用处理了,但是我们知道,还有返回列表对象,列表集合,DataTable对象的几种不同方式,我们也应该要对他们进行一定的封装处理,已达到在子类能够很好使用的目的。

下面我把整个对这几部分封装的代码进行公布,它们的封装的代码如下所示(记得是放在超级抽象类上AbstractBaseDAL即可。

封装好这些超级基类后,我们在数据访问层里面,就可以很好地简化对存储过程的调用了,而且他们的做法都很类似,我们可以对比一下,它们调用存储过程的实现真正简化了很多。

例如对于SqlServer数据访问层,使用超级基类的接口,我们简化代码如下所示。

对于Oracle数据访问层的实现来说,它的接口实现一样简单,只是参数命名有所不同而已。

以上就是我针对《Winform开发框架之存储过程的支持--存储过程的实现和演化提炼》这个主题进行的介绍和分析,希望对大家有所帮助,也希望结合我的框架,迅速开发各种不同的项目。

文章内容有点长,感谢您的耐心阅读和支持。

<a href="http://www.cnblogs.com/wuhuacong/p/4130190.html">Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(1)</a>

<a href="http://www.cnblogs.com/wuhuacong/p/4130525.html">Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)</a>