编程中无法回避的基础知识---事务
进行软件开发已经有一段时间了,有些东西虽然一直在用但是并不是很理解为什么去用它,它的机制又是什么,是不是还有其他的用途?就像我们在对数据库进行一系列操作时,我们为了保证数据的一致性往往会用到事务。本文将简单的介绍一下事务的相关知识,和简单用法。
基本概念
定义
事务是将一系列 数据源更新分组或分批的方法,以便在回滚事务时同时提交所有事务或者不提交任何事务[MSDN]。
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begintransaction和end transaction语句(或函数调用)来界定。事务由事务开始(begintransaction)和事务结束(end transaction)之间执行的全体操作组成。[百度百科]
特性
事务是恢复和并发控制的基本单位。具有4个属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
类型
按事务是否跨越多数据资源来分类:
1)本地事务:事务操作一个数据资源,如数据库和消息队列。在物理上表现为位于同一台计算机。
2)分布事务:事务跨越多个数据源,如操作两个服务器上的数据库。
按事务处理方式划分:
1)手动事务:使用显示指令来控制事务的开始和结束,这种方式可以处理嵌套事务。SQLServer,ADO.NET都提供手动事务处理。
2)自动事务:通过有组件声明事务特性,把组件自动置于事务环境中。使用自动事务不能处理嵌套事务。自动事务的本质是依托于COM+。
简单的实例
实例一
namespace 简单的事务 { class Program { private static Test test; static void Main(string[] args) { test=new Test(); test.Add(); } } public class Test { SqlConnection conn = new SqlConnection("datasource=.;Initial Catalog=Test;Integrated Security=SSPI;Persist SecurityInfo=False"); public void Add() { conn.Open(); SqlCommand command = new SqlCommand("insert intotest2 values(111)", conn); try { command.Transaction =conn.BeginTransaction(); command.ExecuteNonQuery(); command.CommandText = "insert intotest values(222)"; command.ExecuteNonQuery(); command.Transaction.Commit(); } catch (Exception err) { Console.WriteLine(err); Console.ReadKey(); command.Transaction.Rollback(); } } } }
实例二
这是一个简单三层的事务示例,
namespace 事务 //U层的代码 { class Program { static void Main(string[] args) { bll sbll = new bll(); bool flag =sbll.MoveScore(); if (flag == true) { Console.WriteLine("事务执行成功"); } else { Console.WriteLine("事务执行失败"); } } } } namespace AddTestBll //BLL层 { public class bll { private dal dal; public Boolean MoveScore() { SqlConnection sqlCon = new SqlConnection("datasource=.;Initial Catalog=Test;Integrated Security=SSPI;Persist SecurityInfo=False"); //打开连接 sqlCon.Open() ; //定义事务 SqlTransaction sqlTran =sqlCon.BeginTransaction(IsolationLevel.ReadCommitted); //用try...Catch...finally保证事务在出错时会回滚 try { int intResult =dal.Add1(sqlTran); int intResult1 =dal.add2(sqlTran); if (1 == intResult&& 1 == intResult1) { //如果都为真,提交 sqlTran.Commit(); return true; //添加成功 } else { sqlTran.Rollback(); return false; //添加失败 } } catch (Exception e) { //出现异常时,事物回滚 sqlTran.Rollback(); return false; } finally { sqlCon.Close(); } } } } namespace AddTestDal //Dal层 { public class dal { test enTest = new test(); private SQLHelper sqlHelper; public int Add1(SqlTransaction sqlTran) { int intResult = 0; //enTest.Id ="222"; string strSql = "insert intotest values(222)"; intResult =sqlHelper.ExecuteNonQuery(strSql, CommandType.Text, sqlTran); return intResult; } public int add2(SqlTransaction sqlTran) { int intResult = 0; string strSql = "insert intotest values(111)"; intResult =sqlHelper.ExecuteNonQuery(strSql, CommandType.Text, sqlTran); return intResult; } } public class SQLHelper { private SqlConnection conn = null; private SqlCommand cmd = null; private SqlDataReader sdr = null; public SQLHelper() { string connStr = "datasource=.;Initial Catalog=Test;Integrated Security=SSPI"; conn = new SqlConnection(connStr); } private SqlConnection GetConn() { if (conn.State == ConnectionState.Closed) { conn.Open(); } return conn; } ///<summary> ///执行带参数的增删改SQL语句或存储过程 ///</summary> ///<paramname="cmdText">增删改SQL语句或存储过程</param> ///<paramname="paras">参数集合</param> ///<paramname="cType">命令类型</param> ///<returns>返回更新的记录条数</returns> public int ExecuteNonQuery(string cmdText, CommandType cType, SqlTransaction sqlTran) { try { //实例化数据库命令SqlCommand cmd = new SqlCommand(cmdText,GetConn()); //命令类型:存储过程or SQL语句 cmd.CommandType = cType; cmd.CommandTimeout = 180; //设置最大连接时间 //事务 cmd.Transaction = sqlTran; //定义事务执行结果 int intResult =cmd.ExecuteNonQuery(); //执行事务:大于0返回true,否则返回false。 if (intResult > 0) { //事务执行成功 return intResult; } else { //事务执行失败 return intResult; } } catch (Exception ex) { //抛出异常 throw ex; } } } }
上面是两个关于本地事务的小例子,最近项目中用到了分布式而底层还用到了EF,这样就要求运用到分布式事务了,研究中,如果读者有相关的资料希望能分享给大家,谢谢!
文中代码自建了一个测试库里面两张表的表结构如下(记得设置主键)
优秀的博客推荐:
1、.NET简谈事务、分布式事务处理:http://wangqingpei557.blog.51cto.com/1009349/748799/
2、简述.net中有哪几种事务:http://wangzhiyu110.blog.sohu.com/156427139.html
3、.NET简谈事务本质论:http://wangqingpei557.blog.51cto.com/1009349/719056