编程中无法回避的基础知识---事务
进行软件开发已经有一段时间了,有些东西虽然一直在用但是并不是很理解为什么去用它,它的机制又是什么,是不是还有其他的用途?就像我们在对数据库进行一系列操作时,我们为了保证数据的一致性往往会用到事务。本文将简单的介绍一下事务的相关知识,和简单用法。
基本概念
定义
事务是将一系列 数据源更新分组或分批的方法,以便在回滚事务时同时提交所有事务或者不提交任何事务[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