[原创]如何写好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 数据库处理类。

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

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

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

别太懒了。

时间: 2024-09-30 13:19:56

[原创]如何写好SqlHelper 之终章的相关文章

[原创]如何写好SqlHelper

所有写数据库应用的都会遇到SqlHelper.每个人实现的也不同,网上现成的例子也很多.但在实际操作中,大部分都不实用.什么样的才是实用的?答:适合应用场景的! 下面来介绍下我写的一个关于Oracle的SqlHelper.没有进行大规模及性能测试. 首先来说下为什么写这个SqlHelper.在以往的桌面程序开发中,我遇到最多的Sql操作,一般不会涉及多个表同时操作,即使有,在使用SqlHelper时用一个Transaction就可以了. 但现在场景换了.在Web里我们将业务操作与具体数据库操作分

史上最简单的 SpringCloud 教程 | 终章

版权声明:本文为博主原创文章,欢迎转载,转载请注明作者.原文超链接 ,博主地址:http://blog.csdn.net/forezp. 目录(?)[+] 转载请标明出处: http://blog.csdn.net/forezp/article/details/70148833 本文出自方志朋的博客 错过了这一篇,你可能再也学不会 Spring Cloud 了!Spring Boot做为下一代 web 框架,Spring Cloud 作为最新最火的微服务的翘楚,你还有什么理由拒绝.赶快上船吧,老

BugPhobia终章篇章:学霸在线系统Beta阶段展示

0x00 :序言 1 universe, 9 planets, 204 countries,809 islands, 7 seas, and i had the privilege to meet you. 展信安,致以BugPhobia团队的终章 即便对庆典失去兴趣和新鲜感 也选择用仪式感填补生活 就像用纸记下“一二三四”的计划 贴在学校衣柜的铁皮上 0x01 :团队成员简介 图1 BugPhobia团队终章篇章的合影 0x02 :团队项目愿景 0x0200: 学霸在线系统基本定位 网站基本定

JDBC终章- 使用 DBUtils实现增删查改- C3P0Utils数据源/QueryRunner runner连接数据源并执行sql

JDBC终章- 使用 DBUtils实现增删查改 1.数据库结构 Create Table CREATE TABLE `user` ( `id` int(3) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `password` varchar(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 2.工程结构    

OO终章

OO终章 OO完结,这个课程比我想象得要肝,看来暑假得养老了. 感谢各位老师,各位助教带来的全新窝窝,游戏体验良好. 不过,也有遗憾,所以谁能告诉我BUG修复界面长啥样?? OO无伤过 感谢wsb,lsj,shh,xcb,hdl,zyy,lyt,xsy,wjyi,zt几位巨佬的帮助. 10198 lines,0 bugs. 第四单元总结 Project13 类图 大体上是把每个类挂在到类图下,把类的方法.属性挂在到类下,接口的属性和方法因为不涉及查询,故直接忽略. 复杂度 Method ev(G

《吊打面试官》系列-Redis终章_凛冬将至、FPX_新王登基

前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难.作为一个在互联网公司面一次拿一次offer的面霸(请允许我使用一下夸张的修辞手法),打败了无数竞争对手,每次都只能看到无数落寞的身影失望的离开,略感愧疚,在一个寂寞难耐的夜晚,我痛定思痛,决定开始写<吊打面试官>系列,希望能帮助各位读者以后面试势如破竹,对面试官进行360°的反击,吊打问你的面试官,让一同面试的同僚瞠目结舌,疯狂收割大厂offer! 絮叨 男儿

自学.net(1)手写一个sqlhelper类

自学.net已经快一个月了,看的是传智播客的视频,今天正好申请了博客,就先把手写的sqlhelper类上传上去吧 别忘了在解决方案管理器的“引用”添加System.Configuration 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Configuration; 6 using System.Data.SqlClient;

自己动手写操作系统 第四章总结

本章主要内容是建立一个功能比較完好的引导扇区也称为 boot sector 首先回想一下一个操作系统从开机到执行的过程 1.引导 2.载入内核入内存 3.跳入保护模式 4.開始运行内核 可见在内核開始运行前还有非常多工作要做,假设所有交给boot sector,512字节非常可能不够用,所以我们须要将这个 功能分担出来,这个模块就是loader 如今,boot sector 的功能就是负责把loader载入到内存中,而且把控制权交给它,到此,boot sector就完毕任务了 而载入内核的功能就

ASP.NET Core 打造一个简单的图书馆管理系统(九) 学生信息增删(终章)

前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windows <Pro ASP.NET MVC 5>.<锋利的 jQuery> 当此系列文章写完后会在一周内推出修正版. 此系列皆使用 VS2017+C# 作为开发环境.如果