如何写好SqlHelper 之终章

系统 1770 0

精简的美丽......

标题有点大。但是,我觉得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 数据库处理类。

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

 

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

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

别太懒了。

 

如何写好SqlHelper 之终章


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论