实现基于通用数据访问组件的三层架构之补充篇
作为项目性应用系统的架构设计者,我总是追求框架的通用性和易用性。追求通用性,是因为也许当前项目的数据库是SQL Server,而下一个项目就是Oracle,也许当前项目是B/S架构,而下一个项目就是C/S架构,所以,当数据库或者系统架构发生变化的时候,通用性好的项目的框架的代码便不用作任何修改。追求易用性,是因为我见识了很多人包括所谓的技术大牛,为了追求使用某种流行技术的快感,把框架弄得复杂纷繁,一个解决方案下几十个乃至上百个项目,许多犄角旮旯还冷不防的有个配置文件,要把他的系统运行起来,得配置这个配置那个,安装这个再安装那个,要实现一段小小的业务功能,就是做个简单的增删改查,你也得这一层那一个接口的写上一大堆啰啰嗦嗦的代码,而作为一个超级懒人的我,一看见这种框架便深恶痛绝,立刻埋头进去看看有哪些地方可以简化的,总是要把它简化到不能再简化了才觉得满足。之所以要写前面这几篇关于Petshop文章的缘由,便是看到太多人照搬Petshop作架构,搞个什么IDAL,再搞N个xxxDAL层,一个方法,在一个DAL写完了,还要复制到其它N-1个xxxDAL层,运行时还要在配置文件指定一下xxx数据库连接,对应的DAL是xxxDAL。再比如早年接触.NET时间不长时曾参加开发一套房管局的房屋销售登记系统,那时正流行web Service,SOA这些理念,负责架构设计的“大牛”,便硬生生在业务层和web应用层之间插入一个web Service层,所有在业务层实现的方法,都要在web service层添加相应的webmethod,转发业务层的方法,并在应用层配置文件上添加控制开关,控制应用层是直接调用业务层,还是通过web service层调用业务层。”大牛“声称这样的好处是将来业务层有需要的话可以与应用层脱离,成为独立的服务层,这种架构当然很好,很先进,松耦合,完全符合SOA的理念。但是我肯定 这套系统到作废的那天,房管局的人都不会把业务层剥离出来搞个独立的服务器来发布,即使需要向其他系统提供集成服务,由于本身已经是web程序,随便扔个asmx文件到web应用层下就行了。但苦的是我们这些架构的使用者,业务层完成一个方法后,再到web service层加个调用方法,这个工作量倒也不是很大,可是要知道在开发过程中,方法是不断的被修改的,名称,参数,合并甚至删除,而每做一次改动,都要打开web services层去找到对应的方法再接着改一次(很多人调试代码忙起来都会忘这一茬,为此"大牛"经常生气),坑爹啊。
扯得有点远了,我想说的是前一篇随笔里实现的那个demo,我觉得还有优化的地方,从易用性的角度。主要是不满意在应用层的配置文件里,配置数据库连接的时候,还要加上providername,这个providername是什么,对于一般人来说还是不好找的。要说明这个还得从源头上再介绍一下ADO.NET。前文已经说过,微软Sytem.Data.Common命名空间下一系列抽象基类,便是我所讲的ADO.NET抽象基类,其实也可看作是一组ADO.NET的接口,微软自身提供了SQL Server(System.Data.SqlClient)、Oracle(System.Data.OracleClient)、OleDb(System.Data.OleDb)、ODBC(System.Data.Odbc)等几种数据库的ADO.NET接口实现(子类),一般而言,也可称之为ADO.NET Data Provider For SQL Server(Oracle、OleDb、ODBC...),所以,ADO.NET能不能访问某种数据源,就看有没有针对这个数据源的Provider.微软曾经推出过Oracle的Provider,但后来大多数人都使用Oracle自己开发的Provider,据说稳定性和性能比微软的好,于是微软现在就停止了对System.Data.OracleClient的升级了。这些本机上所安装的ADO.NET Data Provider的信息,通常会配置在machine.config上。machine.config上除了微软自身提供的几种provider以外,当你安装一些第三方提供的provider的时候,安装程序就会在machine.config相应节点加入本provider的信息。关于.NET配置文件的读写方面的知识,因与本文主题无关,我这里不作阐述。简而言之,使用DbProviderFactories.GetFactory(string providerInvariantName)创建DbProviderFactory的时候,providerInvariantName便是machine.config关于provider信息的一个属性,DbProviderFactories根据providerInvariantName在machine.config找到所对应的DbProviderFactory实现类的元数据信息,通过反射创建其实例。这个便是微软提供的,它自己也是这么用的创建DbProviderFactory的过程。其实我们的目的不过是要创建DbProviderFactory的实例,没有必要按照微软的这个套路去走,完全可以按照自己的方式去做:
- 直接在配置文件数据库连接串的providerName填入DbFactoryProvider的完全限定名,自己通过反射直接创建。
如config文件
<connectionStrings> <add name="MSSQL" connectionString="Data Source=localhost\sqlexpress; Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient.SqlClientFactory,System.Data, Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"/> </connectionStrings>
dbHelper的构造函数变化如下
public DBHelper(string providerName,string connStr) { // this.dbFactory = DbProviderFactories.GetFactory(providerName); this.connStr = connStr; this.dbFactory = (DbProviderFactory)Type.GetType(providerName).GetField("Instance").GetValue(null); }
- 直接在代码里内置所支持的Provider的信息。事实上对于企业内部信息化系统,一般数据库也就Oracle,SQL Server,再多有个Access,DB2之类,所以索性把这些provider的信息通过代码内置,可以简化配置的信息。代码就不再贴出来了,相信读者参考前面的方式完全可以自己实现。无非就是创建所有要支持的provider的DbProviderFactory实例,放置于缓存里,调用时根据providerName参数挑选便是了。
注意:此文章属博主原创,转载请注明作者信息和原始链接,谢谢合作。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注】。
因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客。