[原创]如何写好SqlHelper 之终章

精简的美丽......

标题有点大。但是,我觉得99%的接近了。

好了,下面我们来说说一个SqlHelper为了适应各种不同的业务需要,它应该具备哪些基本要素。

第一点、可控的事务。

事务是数据库操作的关键部分,在对数据库进行插入、修改、删除时都会用到;事务是基于数据库连接的。一个事务必须要运行在一个连接上,但一个连接上可以有多个事务。

可控的事务就是你在进行数据的增删改时需要一个事务来进行辅助,当操作出错时将修改的数据还原。类似下面的过程

transaction.begin();
    ...do something...
transaction.commit();
or error
transaction.rollback();

当然,你会说,我有部分代码不需要事务。对!向操作日志之类的东西,只要你的语句没错,不管其它的操作成功与否都需要写入数据库。这样的操作就可以护理事务了。

可控的事务其它隐匿包含两种操作。一种是普通的单表增删改操作。一种是多表增删改操作,多见于主从表。

那么,我们需要使用两套(标准或)代码来对以上两种情况进行处理嘛?

第二点,多样的输入方式。

何为输入方式?哈哈,这个很简单嘛!CommandText 与 Parameters。数据库管理系统发展到今天早已经超出使用sql命令的范围,在NoSql数据库越来越成熟的情况下,关系型数据库却依然是主流。所以,哈哈。我们还是谈CommandText 与 Parameters。

向数据库发现Sql命令的方法只有通过文本的形式,然后Parameters的使用却可以为编程以及数据库安全提供帮助。例如:

            var sql = new StringBuilder();
            sql.Append(" INSERT INTO xACCOUNT");
            sql.Append("     (USERID,");
            sql.Append("      ACCOUNT,");
            sql.Append("      EMAIL,");
            sql.Append("      STATE,");
            sql.Append("      PWD,");
            sql.Append("      CREATEOPTION,");
            sql.Append("      PROPERTY,");
            sql.Append("      JOINDATE,");
            sql.Append("      ATTENMODE)");
            sql.Append(" VALUES");
            sql.Append("     (:pUSERID,");
            sql.Append("      :pACCOUNT,");
            sql.Append("      :pEMAIL,");
            sql.Append("      :pSTATE,");
            sql.Append("      :pPWD,");
            sql.Append("      :pCREATEOPTION,");
            sql.Append("      :pPROPERTY,");
            sql.Append("      :pJOINDATE,");
            sql.Append("      :pATTENMODE)");
            return sql.ToString();

如果你需要向数据库中连接插入1W条数据,我想你第一想到的应该是使用带参数的insert语句。为什么?直白点说,数据库对这条语句做出了优化。如果你需要向数据库插入10w以上的数据,那么就不要用这个方法了。有个以datatable方式插入的方法,秒级。

数据安全方面,这个最普通的说法是防止恶意sql语句攻击。百度一下应该大把资料。

第三点,高复杂度与低耦合。

什么是高复杂度。即:所有对数据库的操作高度封装。再解释:.net提供了数据操作的接口对象,如Connectin,Command,Transaction,DataReader,DataAdapter,DataSet,DataTable,Parameter等等对象。这些几乎是数据库操作时必不可少的元素。然后这些对象对于我们的开发来说还是过于分散,因为我们更多的是关心操作的结果。所以,将它们再次封装后,只留下,DataSet,DataTable,DataReader,Execute(),ExecuteScalar()就足够我们使用的了。

什么是低耦合。即:业务类只做业务逻辑相关的事,将数据处理交给数据处理层去做(纯废话,大家都知道的)。这个要怎么实现?

 

下面,我来展示两个图一个文件列表。通过这些来说明上述三点是如何实现的。

图一,类模型

从这个图,你能看到各对象之间的关联。按照.net一个对象一个文件的作法。这也表示,我的文件列中有6个文件。

图二,类结构图。哈哈,这是你最次要想知道的。你最想要知道的是我的代码是什么?有没有可以下载的地方?

最后是文件列表,

 

下面我将正向的介绍这6个文件(类)

1、ErrorObject 。业务基类(blo)的基类。用于描述错误信息。它很简单只有两个属性一个方法。

  属性: IsSucceed,用于判断一个(系列)业务操作是否成功。

  属性:ErrorCode,表示出错的代码。这里只存储出错代码。具体出错信息需要另行存储,以方便管理。

 

2、Blo 。业务类的基类。所有的业务类需要从这里继承。为什么?还记得“可控事务”最后的问题嘛!这个就是答案。

  2.1 独立业务操作

  设:

public class TestA : Blo
{

    public bool Add(object obj)
   {
        Transaction.Begin();
        try
        {
             ............
             Transaction.Commit();
        }
        catch (Exception ex)
        { 
                Transaction.RollBack();
                ErrorCode = -1111;
                throw;
        }
   }
}

 

这里业务类TestA的操作在自己的事务过程中

  2.2 大事务业务操作。

public class TestB : Blo
{

    public bool Add(object obj)
   {
        Transaction.Begin();
        try
        {
      ...... var ta = new TestA();
Transaction.AddBusiness(ta );
        ta.Add(obj); Transaction.Commit(); }
catch (Exception ex) { Transaction.RollBack(); ErrorCode = -1111; throw; } } }

 

这里业务类TestB的操作在自己的事务过程中。而TestA的操作则在TestB的事务过程里。对,没错,它们共享了一个事务过程。

 共享事务过程的办法就是 Transaction 要做的事了。这个过会再讲。

 

3、Dao 数据访问层。说白了就是写sql语句的地方。

在这里你可以直接写sql语句,也可以使用参数的形式。不管使用哪种方法,最终的目的是通过制造sql命令,使用OracleHelper对数据库进行操作,并将得到的结果返回给blo层。

上一个直接sql的代码片段

            using (var helper = new OracleHelper { ConnectionString = txtOracle.Text, CommandText = txtSql.Text })
            {
                var dt = helper.GetDataTable();
                if (dt != null && dt.Rows.Count > 0)
                {
                    foreach (DataRow row in dt.Rows)
                    {
                        lbResult.Items.Add(row.Field<string>("TABLE_NAME") + "\t" + row.Field<string>("COMMENTS"));
                    }
                }
            }

 

4、ParameterList。参数列表对象。

这个对象,在我的上一版本是没有的。之所以现在增加,是因为我在最近写一个导入工具时发现,我原来写的那个helper在对参数进行操作时只能一次性操作。即AddParameter方法只会在调用时才能赋值,而不能在第二次以上的循环中对其赋值。且不能保存对参数列表的引用。

对象中加入了属性操作

public OracleParameter this[string parameterName] 

 

以通过参数名称来快速检索参数对象。内部存储使用的是Dictionary对象。

同时对象增加了CopyTo方法,可以将参数对象全部导出。

5、Transaction 业务逻辑中的事务控制器。

此对象为事务共享时控制是否共用同一事务的关键。主要的方法为

public void AddBusiness(Blo business)

 

将多个需要共享事务的业务对象放到同一事务中。属性 

public bool IsRelated { get;private set; }

 

用于判断是否为共享事务。这个属性为只读的。当业务类进行事务操作时,判断IsRelated是否为true。若为True则跳过事务处理(其实它没有自己的事务处理过程,所以也就没办法提交,只能跳过)。

6、OracleHelper 数据库处理类。

本文的重点,也是大家最熟悉的。每个人的处理方式不同。但接口只要差不多就行了。略过。

 

最后,你最关心的问题,代码在哪里,哪里可以下载!哈哈。。。哈哈。。。

我在这只能说抱歉了。授人以鱼,不如授人以渔。在我这个文的基本上,你动动手,活动活动脑子,我想也能搞个八 九 不 离 十 吧。

别太懒了。

 

posted @ 2014-11-09 14:38  (大贤者模式)  阅读(385)  评论(0编辑  收藏  举报