本文是写在公司部门的网站上的,我懒得作改动了,直接copy到blog上,当中可能有很多不清楚的地方,望谅解。
早上开摩托车的时候突发奇想,假如出于某种原因,我们现在的XXX产品要把数据库换成其他数据库(比如Oracle,db2等),原因嘛,可能是“客户不满sql性能?Oracle白送?sql涨价?Microsoft倒闭?客户是Oracle老总的儿子?”,真的要这样做的话,会发生什么呢?
首先,这肯定是一场灾难,估计一堆人要吐血身亡了。
当然,吐好血之后,就要考虑怎么解决问题了。
由于我们现在XXX(群体替换,应该没漏网之鱼)产品的架构很完美(恩,先拍下马屁)。不知道当初前辈门设计的时候是否已经考虑过这个问题,或者是单纯为了分层,总之,现在的DataAccess layer相对独立,对于替换数据库是很有利的。
先看看现在的一个业务的简化流程:
前面的不看了,看后面的。我的理解如下:
1,业务逻辑层(处理一个具体的业务,比如:<增加一个生徒>这个业务,该业务调用了数据层的诺干个方法,包括AddStudentInfo(),AddStudentEducationInfo()等)
业务层可以调用诺干个DA的诺干个方法,完成这个业务。
顺便说一句:我们现在的XXX产品,业务层几乎形同虚设,把所有的业务逻辑都写到了DA层中。这就导致了DA层的臃肿,难维护(谁知道那几百行的一堆sql代码是怎么干活的啊),代码复用难(几乎是不用想了)。
最理想的状态当然是DA层只处理单一的,具体的一个数据库操作,比如增加生徒基本信息,增加生徒家庭信息,增加生徒教育信息,查询生徒基本信息等等。
然后在BR层中,根据业务的不同需要,组合调用不同的DA。
当然,以上仅仅是理想状态,可能很难实现….
2,数据层(这层是处理一个具体的数据库操作,比如增加生徒基本信息AddStudentInfo(),在这里组织一下sql语句,或者使用存储过程,传入SqlHelper.vb,进行数据库操作)
3,SqlHelper.vb:这个是Microsoft DataAccess Application Block提供的一个数据库操作类,对指定数据库进行操作
DAAB的早期版本(v2.0)只包含了SqlHelper,但后来微软发布的Petshop3.0&4.0(Microsoft用来炫耀.net能力的事例程序)已经包含了OracleHelper。
到了v3.1,DAAB支持的数据库更多,而且使用起来更方便。
废话不多说了,转入正题,该怎么换数据库呢?假如换成Oracle,我们的结构发生如下变化:
我们现有的Sql 数据层不需要做改动,只是额外增加一个Oracle数据层。哪天客户心血来潮,完全可以再换过来…..
要做的改动如下:
1,增加IDAL,把sql DA 抽象出来,放到IDAL中,以便增加其他数据层时,可以有个规范。
工作量一般吧。
2,增加一层,DALFactory,运用到了Abstract
Factory Method。这部很重要,该层的作用是,根据配置信息(或其他途径),反射具体的DAL(sql or oracle)。
这个工作量也不是很大的。不过鉴于我们XXX产品DA层的庞大,还是要做一点工作的。
3,修改BR层。
原本BR直接就调用Sql DA层:
Dim objDA As New RegularExamDA(Me.activeConn)
。。。对objDA进行操作
现在改造一下。需要对接口IDAL进行操作,然后调用DALFactory,DAlFactory会把具体的数据层反射给BR:
Private objDA as IRegularExamDA
objDA =
DALFactory.RegularExamDAFactory.Create()
。。。。对objDA进行操作
工作量也是一般,是辛苦活。
4,增加诺干个OracleDA的project ,对应于我们现在的Sql DA。
当然,DA层中的一些sql语法也要做相应的调整。
比如,(1)sql server 中Getdate()函数取出系统时间,而在ORACLE中是sysdate
(2)sql server 中用top子句,如select top 10
* from 表名
而oracle利用rownum,rownum是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数。
只返回前10条纪录
SQL> select * from 表名 where rownum<11;
这个工作量还是很大的,估计要吐血。
顺便再说一句:我们臃肿的DA又出问题了,那一大堆成千上百行的sql语句要修改成支持oracle,还真是一件很有挑战性的事啊,不知道哪位兄弟姐妹有幸干这活,我为他/她祈祷。阿门!
还有,我们那些sql server上存储过程,Function,也是一个大问题,这些都是和具体数据库关联性极大的冬冬,移植起来肯定很麻烦。尤其我记得早期的Mysql 是没有存储过程的…..
我的建议是,尽量少用数据库的这些功能。存储过程都放到DA去,在DA里些sql语句。Function也不要用,在我们的程序里用其他方法代替吧。
对于在开发中是否充分使用数据库的特性,一直有2种不同意见。一些人认为,数据库的这些特性差异性太大,造成移植性极差,而且很多程序员只对一种数据库比较熟悉,假如换数据库的话,光学习这些特性就要花不少代价。
另一种人却认为使用数据库的特性,能提高开发效率,提高程序性能,and 其他一堆好处。
具体用哪种,请视具体情况。不过显而易见,我是前者的拥护者,呵呵。
5,增加OracleHelper.vb,和sqlhelper放一起吧,对照下sqlhelper,不需要改多少东西的。
这个没啥工作量
至此,改造差不多完成了,问题。。。。应该还是有的。
将来要换回sql,只需要修改配置文件(或者在login画面加选项)。恩,用户可以每天换一个数据库了。
假如还要增加一个其他数据库(db2,Sybase,mysql?),只要增加一个XXXDA,然后继承IDAL,写出相应的DA代码,就可以了。
同时,用户也可以同时使用数个数据库,比如生徒放sql,教师放Oracle,完全没有问题的。
当然,我们XXX产品是不太可能换数据库的,不过对于其他项目同样适用。
比较诱人的是,只要把这个架构搭建好,不管将来的项目用何种数据层,都可以套用。
付上最新版的DAAB(v3.1):
已经不在分sqlhelper,oraclehelper了,由AdoHelper自动选择合适的数据库连接类来连接,支持SqlServer, Oracle, OleDB, ODBC不同类型的连接。
水平有限,文中一堆错误需要指正。谢谢。