一个中型OA系统的架构过程(二)

接上文,我们讲解了UI界面层的在设计初期的架构部分,由于是在系统分析还没有全面展开的情况下先做的初期架构,所以中间业务逻辑部分我们暂时放下,先来考虑数据访问层的一些问题。

    2.数据访问层:分两个工程,一工程主要封装数据库访问及操作的对像,我将其命名为DataBaseOption,另一工程主要功能为负责业务逻辑对操作数据库部分的功能进行构造一些操作数据库的规则然后调用DataBaseOption的对像进行对数据库的操作,在这里我把它命名为DataAccess。其中DataAccess与业务逻辑有关,在这里暂时先放一边,而DataBaseOption我们可以看作仅仅与数据库有关,所以在这里我们先作这一部分的讨论。

    对于数据库的操作,我们最常用的就是查询/插入/更新/删除,当然对于一个OA系统来说,还应该多加一个,那就是事务。

    对于查询,我们在这里应该考虑的有直接传入SQL语句查询或者存储过程的查询,当然视图在这里你已经可以把它当一个表看待了,暂时不考虑。查询返回的值,对于DotNet来说,最常用的可能就是返回DataSet,DataReader了,而DataTable被包含于DataSet之中。

    于对插入和更新,其实我们可以放在一起考虑的,因为插入本身就是更新了数据库,而插入或者更新的方法当然可以用SQL语句实现,这些通用的方法在这里我们还是得考虑的。再而就是用数据集更新数据库,也就是用一个适配器更新一个记录集(DataSet)。当然在更新记录集当中我们也可以对记录集里面的一些记录进行删除,然后用记录集更新数据库,达到删除数据的目的。

    至于删除,就没有什么好说的了,删除比较简单。
    对于事务,能够创建/结束与回滚。

    好了,有了上面的分析,现在我们开始思考如何架设这个类。首先当然得有个数据库连接,为了严格地不让这个连接在别的地方使用,我们定义为:

    private OracleConnection conn = new OracleConnection;
    private string connString;

    为了能实现DataSet更新数据库,我们还得定义一个OracleDataAdapter:
    private OracleDataAdapter upDateAdaper;

    同时我们还得定义一个连接字符串,这个串,为了方便我们的开发,把它定义为一个属性,便于我们把它存放于任何地方,比如存放在Web.config配置文件里。
  public string ConnString
  {
   get
   {
    return connString;
   }
   set
   {
    connString = value;
   }
  }
 
   好了,到了这里,我们得考虑性能的问题,如果一个连接长期连接的话,会占用很多的资源,所以在这里我们要保证在对数据进行操作的时候连接是打开着的,同时,当我们的操作结束的时候,连接马上关闭。如何实现呢?在这里可以定义一个数据库连接的方法,判断conn的State返回或者从新打开一个连接。当我们用完这个连接后,记得Close()一下就可以了。

    查询返回值问题,我们定义两类,一类是DataSet,一类是OracelDataReader。
    public DataSet GetDataSet(string sql)
    {
    }
    public DataSet GetDataSet(string tableName,string fields,string condition)
    {
    }
    public static DataSet ReturnDataSet(……)
    ……

    public OracleDataReader GetDataReader(string sql)
    {
    }
    public OracleDataReader GetDataReader(……)
    {
    }
    public static OracleDataReader ReturnDataReader(……)
    {
    }
    ……

    由上面给出的部分代码,我们可以看到有部分是static类型的,定义为static类型主要是为了方便引用,而仅仅为public类型DataSet方法,则要考虑到更新数据库的问题,也就是说生成一个DataSet的同时要生成一个Adapter,在后面部分的更新程序里面要保证这个在逻辑层已经被更改过的DataSet能够Update到数据库里,当然这些说明应该在方法体上面的XML注释里说明。

    在这里我们应该注意一点,也就是仅有一个sql参数及有三个参数的GetDataSet的区别,这两个东东的作用几乎是一样的,为什么写两个呢?这个是考虑到数据库的问题,也就是说,如果你的系统在开发阶段控制得很好,所有SQL语句全由DataBaseOption构造,那么,如果你把你的数据库从Oracle改为Sql Server的时候,可能你只要改变这个数据库操作类就可以实现了;但是如果你的sql语句由DataAccess构造,然后传给只有一个参数的GetDataSet,由于每种数据尽管都支持标准的SQL,但是也有些差别,所以当你进行数据库移植时,有可能得同时修改DataAccess,DataBaseOption的代码。当然了,如果你的系统根本就不会出现这种改变数据库容器的问题,你根本就不用考虑这么多。

    设计了数据的查询后,我们来思考一下数据的更新问题,前面说到了,有用SQL语句更新和DataSet更新,在这里特定于这个系统来说,我们在第一部分还说到了用Hashtable保存数据然后更新的问题,所以在这里我们还得考虑如果用Hashtable更新DataSet,然后再更新数据库。废话少说。

    public enum UpdateOption{insert,update};
    public int UpdateData(string sql)
    {
    }
    public int UpdateData(DataSet myDataSet)
    {
    }
    public int UpdateData(string tableName,Hashtable hsTable,UpdateOption option)
    {
    }
    public int UpdateData(……)
    {
    }

    同样,在这里也应该有static类型的。
    ……

    在这里,传入一个DataSet如果更新数据库呢?首先在生成DataSet的时候我们要new一个DataAdapter,然后把这个Adapter暂时寄存于upDateAdaper中,在UpdateData里面再调用upDateAdaper来update这个DataSet,至于代码如何编写,有什么技巧性的问题,这个已经属于编码者的问题了。同样像OracleCommand这些东西,由于仅仅与编码者有关,在这里不作分析。

    数据的删除问题,一部分已经在数据更新里面实现,另一部分就是用Sql语句实现,这些不用多说。比如写一些通用的ExecuteNonQuery方法则可。

    事务问题,其实在大型的数据库里都已经有事务处理功能了,我们的任务就是写通用的方法创建/结束/回滚事务,方便在DataAccess里面调用。

    由于小梦在出差,时间比较紧,在这里就不能作很详细的介绍了,其实对于数据库操作类,仅仅是那些方法体的参数,都得考虑半天,真正在作架构的时候,你必须得考虑得全面,因为这个关系到你架构逻辑层引用的问题。同时,你必须要很详细的注明每一个方法体的功能及其参数的说明,否则编码人员不知道你的意图如何,到时候就有可能出现偏差。如果你懂Rose(Rose不支持DotNet,要用Rational XDE Developer for .net)用它来架构然后生成代码,会节省你很多的时间。

    有了界面层和数据操作层,我们举个例子说明它的工作过程:
    首先,我们的程序员对照着数据库设计文档设计一个Form(拖动输入控件设置Name属性)-->生成一输入窗体-->点击保存-->传表名及带有表信息的哈希表给业务外观层-->调用DataAccess相应的类及方法-->调用DataBaseOption的UpdateData(string tableName,Hashtable hsTable,UpdateOption option)方法,实现数据的插入/更数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值