编程中无法回避的基础知识---事务


编程中无法回避的基础知识---事务

        


         进行软件开发已经有一段时间了,有些东西虽然一直在用但是并不是很理解为什么去用它,它的机制又是什么,是不是还有其他的用途?就像我们在对数据库进行一系列操作时,我们为了保证数据的一致性往往会用到事务。本文将简单的介绍一下事务的相关知识,和简单用法。

 

         基本概念

 

         定义

         事务是将一系列 数据源更新分组或分批的方法,以便在回滚事务时同时提交所有事务或者不提交任何事务[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

上一篇:Android——Fragment


下一篇:android事件分发原理及源码简读