同生共死的事务

      我对事务的认识还很少,以前我知道数据库中有事务的存在,而不知在我们的C#程序中也可以加入事务,在程序中实现。通过我的分析,在程序中的事务好像偏向于业务方面,而在数据库中的事务,便向于数据方面。对于事务中的锁,在此我并没有进行总结,仅是总结了一下事务的概念和事务的基本用法。

数据库中的事务:

(1):事务(Transaction)是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,以便服务器保持数据的完整性。

(2):事务通常是以BEGIN TRANSACTION开始,以COMMIT或ROLLBACK结束。

COMMIT表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据库的更新写回到磁盘上的物理数据库中去,事务正常结束。

ROLLBACK表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有以完成的操作全部撤消,滚回到事务开始的状态。

(3):事务运行的三种模式:

A:自动提交事务

          每条单独的语句都是一个事务。每个语句后都隐含一个COMMIT。

B:显式事务

       以BEGIN TRANSACTION显式开始,以COMMIT或ROLLBACK显式结束。

C:隐性事务

       在前一个事务完成时,新事务隐式启动,但每个事务仍以COMMIT或ROLLBACK显式结束。

(4):事务的特性(ACID特性)

A:原子性(Atomicity)

       事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。

B:一致性(Consistency)

       事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

C:隔离性(Isolation)

      一个事务的执行不能被其他事务干扰。

D:持续性/永久性(Durability)

      一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

 

使用事务的方式事例:

第一种:try……catch

BEGIN TRANSACTION T1

BEGIN TRY
    
      insert into [teach_info]([teach_id],[login_name],[login_pwd],[real_name],[state]) values(@id,@login_name,@pwd,@name,@state);

       delete from [tmpUser] where [login_name]=@login_name;

      COMMIT TRANSACTION T1

END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION T1;
END CATCH;

第二种:用全局变量@@error

BEGIN TRANSACTION T1
      insert into [teach_info]([teach_id],[login_name],[login_pwd],[real_name],[state]) values(@id,@login_name,@pwd,@name,@state);

     if @@Error<>0 begin

           ROLLBACK TRANSACTION T1;--回滚事务

           return;

     end
      delete from [tmpUser] where [login_name]=@login_name;

      if @@Error<>0 begin

           ROLLBACK TRANSACTION T1; --回滚事务

           return;    --别忘了返回语句,不然下面语句会继续执行,使存储过程报错

     end
      COMMIT TRANSACTION T1  --执行到这说明以上的执行都成功,提交事务

 

C#中的事务:

下面的代码中,我们想执行两个更新操作,在表T_User中将A用户的积分减100,将B用户的积分加100,如果任何其中一个操作失败,那我们就撤销。要么两个都更新数据,要么就一个也不更新。 

using ( SqlConnection conn = new SqlConnection( connectionString ) ) 

conn.Open(); 
SqlTransaction transaction = conn.BeginTransaction(); 
SqlCommand cmd1 = conn.CreateCommand(); 
cmd1.CommandType = CommandType.Text; 
cmd1.CommandText = "Updata T_User set Integral=Integral-100 where UserName=@username"; 
cmd1.Parameters.Add( new SqlParameter( "@username ", A) );
SqlCommand cmd2 = conn.CreateCommand(); 
cmd2.CommandType = CommandType.Text; 
cmd2.CommandText ="Updata T_User set Integral=Integral+100 where UserName=@username"; 
cmd2.Parameters.Add( new SqlParameter( "@username ",B) );
try 

cmd1.ExecuteNonQuery(); 
cmd2.ExecuteNonQuery(); 
//如果执行到这里,还没出错,那说明两个操作都成功了,我们就提交事务,让这两个更新都生效。 
transaction.Commit(); 

catch 

//如果执行到这里,就说明肯定有操作失败了,那么我们就回滚操作,回滚的范围就是自多调用BeginTransaction之后在该数据库连接上执行的所有事务操作。两个用户的积分保持不变 
transaction.Rollback(); 



posted @ 2011-11-25 14:44  孤星缀月  阅读(324)  评论(0编辑  收藏  举报