zoukankan      html  css  js  c++  java
  • 重温Petshop 谈谈对三层架构的理解兼发布一个通用的数据访问控件(oracle免装客户端)

        编写这个组件的需求灵感来自于看了某个产品(企业应用系统)研发项目的源码,该产品为了同时支持sql server 和oracle,

    照搬了微软的 petshop的代码作为系统架构,petshop相信很多.net程序员都非常熟悉了,里面所展示的三层架构大意是这样的

    UI层,BLL层,DAL层,UI层使用BLL层的服务对象,BLL使用DAL层的服务对象,其中BLL层对DAL层的引用使用的是接口,通过配置文件动态加载指定的DAL实现,

    DAL通过使用不同的数据库ADO.NET组件,调用不同的SQL语句,如 Oracle DAL 使用了System.Data.OracleClient下的OracleConnection,OracleCommand...,

    SQLServer DAL使用了System.Data.SqlClient下的SqlConnection,SqlCommand等,实现了针对不同数据库的支持。

    于是,这个产品的开发人员,都是这么个过程编写代码的,首先,打开UI层,当需要对数据进行某项操作时,比如 GetProduct(int id) 编写好2条sql语句,1条sql server版(select * from product where id = @id),放置于一个专门存放sql server的sql语句的xml文件中,一条oracle版的(select * from product where id =:id),放置于一个专门存放Oracle的sql语句的xml文件中,然后在IDAL层定义方法接口,同时在SQL Server DAL和Oracle DAL各 定义一个实现方法执行该sql,

    大致如下

     idal:

    public interface  IProduct

    {

     product  GetProduct(int id);

    }

     

    sqlserver dal:

    public class ProductDal: IProduct 

     publilc product GetProduct(int id)

    {

      reuturn SqlHelper.ExecuteDataSet(sqlserver.sql)...

    }

    }

    oracle dal:

    public class ProductDal: IProduct 

      publilc product GetProduct(int id)

    {

      reuturn oracleHelper.ExecuteDataSet(sqlserver.sql)...

    }

    }

    SQLhelper 代码大致如下

     public ExecuteDataSet(string sql)

    {

      using(SqlConnection conn = new SqlConnection)

     {

    .....

    }  

    }

    Oraclehelper 代码大致如下

     public ExecuteDataSet(string sql)

    {

      using(OracleConnection conn = new SqlConnection)

     {

    .....

    }  

    }

    然后再在BLL层定义方法,

    idal = DALFactory.DataAccess.CreateProduct();  (通过配置文件指定返回实现的DAL)

     publilc product GetProduct(int id)

    {

      reuturn idal.GetProduct(id);

    }

    至此,UI层终于可以调用BLL的方法了。结果就是 DAL层庞大无比,有无数个类和方法,而BLL呢,没有实质性代码,简直就是为了达到三层架构而拼凑出来似的,纯粹就是为了"三层"而"三层"。

    事实上,我认为,数据层应该提供的是数据服务,即每个数据库对象(表,视图,存储过程)的crud,而和业务逻辑无关,而BLL通过调用这些数据服务,形成UI层需要的数据,并返回给UI,而UI层,只负责响应界面上用户的操作,对数据的加工处理,则交给BLL完成,这才是三层的分工职责。

    像上面误解三层架构的地方其一是 没有真正理解数据访问层的负责提供数据服务的概念,实质上是把ui层需要什么都数据,都交给数据访问层去实现,petshop作为一个示例代码项目,为了通俗易懂,bll写的比较简单,却给一些人造成了误解,以为bll就是一个代理层。

    其二是如果为了使产品适应不同的数据库,这种架构未免太罗嗦,首先要定义接口,然后针对sql server写一个实现方法, 然后针对oracle再写一个实现方法, 方法内容大多数情况下一模一样的,实际上微软的ADO.net组件里早就提供了一组通用的抽象基类,位于System.Data.Comm下,DbConnection,DbCommand...,  System.Data.SqlCient和System.Data.OracleClient下的SqlConnection,OracleConnection均继承于对应的抽象基类,微软设置连创建这些组件的工厂类都建立好了,DbProviderFacoty,实现子类SqlClientFactory,OracleClientFactory...,事实上,我们完全可以用使用通用ADO.net组件来编写我们的

    xxxDBHelper类,这样对于dal,无需使用接口,无需多个针对数据库的实现,

    比如 

    DBHelper:

     public ExecuteDataSet(string sql)

    {

      using(DbConnection conn = DbProviderFacory.Instance.CreateConnection())

     {

    ....

    }

    DAL里不必再考虑多个库的实现,直接

    DBHelper.ExecuteDataSet(sql);

    我们需要做的,无非就是在初始化的时候,创建指定的DbProviderFacory,实际上配置文件的数据库连接里就有

    ProviderName这一项,就是用来指定DbProviderFacory(微软其实已经提供了我们所需要的一切),而在machine.config,已经内置了微软的针对不同数据库的DbProviderFacory,如SQL Server,Oracle,OleDb,ODBC等,

    说得简单点,只要我们在配置文件的数据库连接配置里,填上连接字符串,填上ProviderName,我们就能根据

    ProviderName得到我们的DbProviderFacory,然后通过DbProviderFacory创建我们执行sql需要的Connction,Command等ADO.net 对象,我们在代码中无须再关心数据库的异同。

    所以,我编写了DBClient,里面主要就一个类,DataAccess,提供的功能类似于petshop里面的sqlHelper,oracleHelper,只不过我使用的DbConnection,DbCommand等,

    使用起来很简单,

    DataAccess dataAccess = new DataAccess(providerName, connstring);

    dataAccess.ExecuteDataSet(sql)....

    你的providerName指向的是oracle provider,就会创建出oracle的ado组件执行sql,指向sql server provider,则会创建出sql的ado组件执行sql。

    另外,在oracle provider我使用了oracle官方的oracle.dataaccess.dll,不仅性能和稳定性比微软自己的system.data.oracleclient.dll强(微软已宣布停止了该组件的发布),而且运行时带上相关的dll,还能免装

    oracle 的客户端。

  • 相关阅读:
    29 顺时针打印矩阵(四-画图让抽象问题形象化)
    27 二叉树镜像(四-画图让抽象问题形象化)
    java的4种代码块
    Eclipse中连接Sql Sever2008 -----转自Yogurshine
    java之HashMap的遍历Iterator
    java之插入排序
    java之选择排序
    java之冒泡排序
    java之快速排序
    java之折半查找
  • 原文地址:https://www.cnblogs.com/lindping/p/2090834.html
Copyright © 2011-2022 走看看