周末了比较清闲,把自己的orm框架整理了下,开源了.

  已经做出来的东西通常感觉有些简单,一些新手或许听到"框架"一类的词觉得有些"高深",简单来说orm就是把ado的封装.

在介绍这个框架的第一篇博文,已经把DalBase介绍了一下设计思路,本篇的DBHelper对象也是给dalBase来用的,可以说框架的所有定义对象都是为了它.

这里起名叫DBHelper,因为我也是从写SQLHelper开始的,DBHelper只不过是所有类型对ado操作的各种方法的封装,所以本篇博文希望给c#新手,或是对ado.net认识比较模糊的有一些帮助.

首先DBHelper定义是个抽象的,因为我不知道DalBase 到底要访问哪种数据库,但我知道不管哪中数据库都会有链接字符串,那我就要求,必须要有连接字符串.

public DbHelperBase(string connStr)
{
_ConnStr = connStr;
}

DbHelper是个抽象的,那它的成员必然就不能有具体对象.

那就把ado.net常用的对象定义出来.(如果你是初学者,我的建议是 用到哪个对象再去定义,否则到后期自己都不知道定义它干啥呢)

        protected abstract DbConnection DBConnectionObj { get; }
protected abstract DbCommand DbCommandObj { get; }
protected abstract DbDataAdapter DbDataAdapterObj { get; }
protected DbTransaction DbTransObj; public DbConnection CurrentConnection
{
get
{
return DBConnectionObj;
}
}

说明一下,为什么事务对象不是抽象的,因为事务对象始终是有DbConnection来创建的,我不用知道它具体是什么类型.

DbConnection 对象public也是为了扩展其它功能而存在的.

定义了是否事务的变量,所有ado操作都会判断当前是否处于事务的标记.

bool _IsTrans = false;

初学.net的朋友,应该都会有一个SQLHelper的类,我也曾经看过都大同小异,而且普遍都没有事务的实现,如果你中枪了,那么恭喜你,你即将会改变你sqlHelper的实现.

如下代码:

     /// <summary>
/// 执行一条指定命令类型(SQL语句或存储过程等)的SQL语句,返回所影响行数
/// </summary>
public int ExecNonQuery(string sqlText, CommandType cmdType, params DbParameter[] param)
{
using (SqlConnection conn = new SqlConnection(_ConnStr))
{
using (SqlCommand cmd = new SqlCommand(sqlText, conn))
{
cmd.CommandType = cmdType;
if (param != null)
cmd.Parameters.AddRange(param);
conn.Open();
return cmd.ExecuteNonQuery();
}
}
}

以上代码看起来是没什么问题,但如果要启用事务的话想想是否可以实现呢?

如果说改造一下加上事务的代码就行的话

如下:

 SqlTransaction tran = conn.BeginTransaction();
cmd.Transaction = tran;

这样显然是错的,因为我们往往多条执行语句通常是分多次调用 ExecNonQuery() 方法的.

这样的一个ado方法的封装显然是不合理的.

如果多个增删改查(注意:查询也可能在是事务里)的方法,在一个事务里,那么必须是一个数据库连接(Connection)

这就是为什么把那三个对象定义到外面的原因之一了,最重要的原因是我需要子类去重写它.

下面看看我的实现:

        /// <summary>
/// 打开连接,如果已经打开则什么都不执行了
/// </summary>
void OpenConnection()
{
if (DBConnectionObj.State != ConnectionState.Open)
{
DBConnectionObj.ConnectionString = _ConnStr;
DBConnectionObj.Open();
}
}
        /// <summary>
/// 给当前DbCommand对象赋值,并且OpenConnection();
/// </summary>
void SetCommandAndOpenConnect(string sqlText, CommandType cmdType, params DbParameter[] param)
{
//按说赋值Connection,CommandType,是不用多次赋值的
DbCommandObj.CommandType = cmdType;
DbCommandObj.Connection = DBConnectionObj;
DbCommandObj.Parameters.Clear();
if (param != null)
{
DbCommandObj.Parameters.AddRange(param);
}
DbCommandObj.CommandText = sqlText;
OpenConnection();
}
        /// <summary>
/// 执行一条指定命令类型(SQL语句或存储过程等)的SQL语句,返回所影响行数
/// </summary>
public int ExecNonQuery(string sqlText, CommandType cmdType, params DbParameter[] param)
{
try
{
SetCommandAndOpenConnect(sqlText, cmdType, param);
return DbCommandObj.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
CloseConnect();
}
}

看到这三个方法或许对于初学者会感到迷茫了,没有看到任何有关事务的代码呢,兜个圈子,现在想象一下如果加事务的话,需要做什么?

我们先从理论上认识一下,事务处理的流程

1.指定事务是哪个Connection

2.Command的事务对象指定到该事务.

3.Open()

4.提交或回滚(我是能写汉字的地方绝不写拼音)

5.关闭连接.

继续说这几个方法,为什么定义SetCommandAndOpenConnect 和 OpenConnection 这两个方法,本着尽量减少重复代码的原则.仅此而已.

既然Connection和Command都已经定义到方法外了,那就是说我只要再执行Command.ExecuteNonQuery()方法前,给他们赋值就行了.

也就是开始事务只需要给这个两个对象赋值即可

事务的相关代码如下:

        /// <summary>
/// 开始执行事务
/// </summary>
public void TransStart()
{
OpenConnection();
DbTransObj = DBConnectionObj.BeginTransaction();
DbCommandObj.Transaction = DbTransObj;
_IsTrans = true;
}
/// <summary>
/// 事务提交
/// </summary>
public void TransCommit()
{
_IsTrans = false;
DbTransObj.Commit();
CloseConnect();
}
/// <summary>
/// 事务回滚
/// </summary>
public void TransRollback()
{
_IsTrans = false;
DbTransObj.Rollback();
CloseConnect();
}

这就是事务的方法了.

最后一个CloseConnect()方法,差点把它遗忘了

        /// <summary>
/// 关闭连接,如果没有开始事务或连接打开时才关闭
/// </summary>
void CloseConnect()
{
if (!_IsTrans)
{
if (DBConnectionObj.State == ConnectionState.Open)
{
DBConnectionObj.Close();
DBConnectionObj.Dispose();
}
}
}

当开始事务时,连接是不能关的.只有提交了或回滚了才会把当前连接断掉.

到这里其实DbHelper的设计基本完成,再贴一下关于查询的几个方法,和执行类似就不解释了.

     /// <summary>
/// 获得首行首列
/// </summary>
public object GetScalar(string sqlText, CommandType cmdType, params DbParameter[] param)
{
try
{
SetCommandAndOpenConnect(sqlText, cmdType, param);
return DbCommandObj.ExecuteScalar(); }
catch (Exception ex)
{
throw ex;
}
finally
{
CloseConnect();
}
}
     /// <summary>
/// 执行一条SQL语句返回DataSet对象
/// </summary>
public DataSet GetDataSet(string sqlText, CommandType cmdType, params DbParameter[] param)
{
try
{
SetCommandAndOpenConnect(sqlText, cmdType, param);
DbDataAdapterObj.SelectCommand = DbCommandObj;
DataSet ds = new DataSet();
DbDataAdapterObj.Fill(ds);
return ds;
}
catch (Exception ex)
{
throw ex;
}
finally
{
CloseConnect();
}
}      /// <summary>
/// 获得DataReader对象
/// </summary>
public DbDataReader GetDataReader(string sqlText, CommandType cmdType, params DbParameter[] param)
{
try
{
SetCommandAndOpenConnect(sqlText, cmdType, param);
CommandBehavior cmdBehavior = CommandBehavior.CloseConnection;
if (_IsTrans)
{
cmdBehavior = CommandBehavior.Default;
}
DbDataReader dbReader = DbCommandObj.ExecuteReader(cmdBehavior);
return dbReader;
}
catch (Exception ex)
{
throw ex;
}
finally
{
//DataReader用dbReader对象来关闭
//CloseConnect();
}
}

这里需要注意的是关于返回DataReader对象时不能关闭Connect,和 cmdBehavior 的赋值.

好了,到这DBHelper的设计和核心代码已经全部实现了.

试想一下我现在要完成SQLServerHelper的实现需要做的是什么?

当然只要实现父类的那几个抽象属性就行了.

代码如下:

 public class SQLHelper : DbHelperBase
{
public SQLHelper(string connStr)
: base(connStr)
{ } SqlConnection _DBConnectionObj;
SqlCommand _DbCommandObj;
SqlDataAdapter _DbDataAdapterObj; protected override DbConnection DBConnectionObj
{
get
{
//SqlBulkCopy aa = new SqlBulkCopy(new SqlConnection());
if (_DBConnectionObj == null)
{
_DBConnectionObj = new SqlConnection(_ConnStr);
}
return _DBConnectionObj;
}
} protected override DbCommand DbCommandObj
{
get
{
if (_DbCommandObj == null)
{
_DbCommandObj = new SqlCommand();
}
return _DbCommandObj;
}
} protected override DbDataAdapter DbDataAdapterObj
{
get
{
if (_DbDataAdapterObj == null)
{
_DbDataAdapterObj = new SqlDataAdapter();
}
return _DbDataAdapterObj;
}
} }

OracleHelper,oledbhelper,SQLiteHelper,就不贴代码了.

转载建议标明出处(我从来不强迫别人做我管不了的事).

整个框架的源码在介绍框架的第一篇博文里有.

欢迎吐槽,点赞,建议,批评,指正,抄袭.

c# 轻量级 ORM 框架 之 DBHelper 实现 (三)的更多相关文章

  1. 轻量级ORM框架初探-Dapper与PetaPoco的基本使用

    一.EntityFramework EF是传统的ORM框架,也是一个比较重量级的ORM框架.这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择. 1.1 准备一张数据库 ...

  2. c# 轻量级ORM框架 实现(一)

    发布一个自己写的一个轻量级ORM框架,本框架设计期初基于三层架构.所以从命名上来看,了解三层的朋友会很好理解. 设计该框架的目的:不想重复的写增删改查,把精力放到功能实现上. 发布改框架的原因:希望给 ...

  3. 轻量级ORM框架 QX_Frame.Bantina(二、框架使用方式介绍)

    轻量级ORM框架QX_Frame.Bantina系列讲解(开源) 一.框架简介 http://www.cnblogs.com/qixiaoyizhan/p/7417467.html 二.框架使用方式介 ...

  4. 轻量级ORM框架 QX_Frame.Bantina(一、框架简介)

    轻量级ORM框架QX_Frame.Bantina系列讲解(开源) 一.框架简介 http://www.cnblogs.com/qixiaoyizhan/p/7417467.html 二.框架使用方式介 ...

  5. .NET轻量级ORM框架Dapper入门精通

    一.课程介绍 本次分享课程包含两个部分<.NET轻量级ORM框架Dapper修炼手册>和<.NET轻量级ORM框架Dapper葵花宝典>,阿笨将带领大家一起领略轻量级ORM框架 ...

  6. 轻量级ORM框架Dapper应用一:Dapper安装

    一.Dapper简介 Dapper是一款轻量级ORM框架,为解决网站访问流量极高而产生的性能问题而构造,主要通过执行TSQL表达式而实现数据库的CQRS. 如果你在项目中遇到性能访问问题,选择Dapp ...

  7. C# 性能优化 之 秒表 Stopwatch。 Dapper一个和petapoco差不多的轻量级ORM框架

    Sweet小马 小马同学的编程日记. C# 性能优化 之 秒表 Stopwatch. 生词解释:Diagnostics[,daɪəg'nɑstɪks] n.诊断学 using System.Diagn ...

  8. 分享自己写的基于Dapper的轻量级ORM框架~

    1.说明 本项目是一个使用.NET Standard 2.0开发的,基于 Dapper 的轻量级 ORM 框架,包含基本的CRUD以及根据表达式进行一些操作的方法,目前只针对单表,不包含多表连接操作. ...

  9. 轻量级ORM框架 Bankinate

    [前言] 前面讲过ORM的前世今生,对ORM框架不了解的朋友可以参考博文:https://www.cnblogs.com/7tiny/p/9551754.html 今天,我们主要通过设计一款轻量级的O ...

随机推荐

  1. 讲解HTML服务器推送相关技术知识(转)

    1. 为什么需要服务器推送? 最大的优点:实时 健康知识平台重庆男科医院 重庆妇科医院适用场景:实时股票价格.商品价格.实时新闻.Twitter/weibo timeline.基于浏览器的聊天系统 2 ...

  2. Appium过程中用到的adb点滴知识库

    一.认识abd adb是什么? adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb我们可以在Eclipse中方面通过DDMS来调试Android程序,说白了就是d ...

  3. Sikulix IDE简介

    打开sikuklixIDE 这里介绍下使用方式 可以看到左边的menu 有查找,鼠标动作和键盘动作 我们先用百度搜索做个例子 打开firefox,输入www.baidu.com 点击左边的Click, ...

  4. 【LeetCode】66 & 67- Plus One & Add Binary

    66 - Plus One Given a non-negative number represented as an array of digits, plus one to the number. ...

  5. Zookeeper Hello World

    1.Zookeeper的安装使用 在官网上下载zk的安装包(http://labs.renren.com/apache-mirror/zookeeper/),解压后cd到zk的目录下. 单机版安装方法 ...

  6. WS之cxf与spring整合2

    在action中加入webservice

  7. WS之cxf简单实现

    1.服务端实现: 1.1 定义接口,用@WebService修饰: /** @WebService 所修饰的接口,那么接口里面的方法全部都属于web的服务  */ @WebService public ...

  8. LeetCode(5) - Longest Palindromic Substring

    这道题要求的是给你一个string, 如“adcdabcdcba",要求返回长度最大的回文子字符串.这里有两个条件,一是子字符串,而是回文.用纯暴力搜索的话,需要用到O(n^3)的时间,必然 ...

  9. c#装B指南

    要想让自己的代码,看起来更优雅,更有逼格,更高大上,就一定要写出晦涩难懂,而又简洁的代码来. 对于类自身的全局变量,一定要加this,对于基类的,一定要加base.反射不要多,但一定要有,而且偶尔就来 ...

  10. dom 筛选器

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...