在程序中使用事务是我们处理并发数据操作常用的方法,例如,要从用户的输入中得到数据,进而更新表T1,这时由于T1与表T2数据存在关联,T1数据的变化,T2要删除一条相应的记录(可以是计算出的),如果T2删除失败,那么之前的操作应回到原始的值,并通知用户操作失败。这时事务就有它的用武之地了。我们可以将SQL语句写到一个字符串中,使用以下方法执行:
/// <summary>
/// 执行基本SQL语句
/// </summary>
/// <param name="sqlStr">要执行的SQL语句</param>
/// <param name="err">错误消息</param>
protected static void _ExeSQL(string sqlStr,ref string err)
{
SqlConnection conn =DBBaseData.GetConn();
conn.Open();
SqlCommand cmd = new SqlCommand();
SqlTransaction tran = conn.BeginTransaction(IsolationLevel.ReadCommitted);//定义事务
cmd.CommandText = sqlStr; //此sqlStr可以是多条数据库操作语句
cmd.Connection = conn;
cmd.Transaction = tran;
try
{
cmd.ExecuteNonQuery();
tran.Commit();
}
catch (Exception e)
{
err = e.Message;
tran.Rollback();
}
finally
{
conn.Close();
}
}
有时候程序中的事务并不能胜任所有任务,当在存储过程中需要回滚部分操作时,就要使用T-SQL事务了,事务的作用不但是记录执行,还可以回滚,这是使用它的关键所在,在T-SQL中我们可以借助系统全局变量@@Error要得到上一条语句的异常,正常情况下它是返回0的。
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
我们看到这样两条语句还可以,但是语句多了要使用多条判断语句,好像有点多余了,SQL2005解决了这个问题,它的try...catch 块可以一次捕获到其中的异常,并在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;