C#数据库事务原理及实践

使用存储点

事务只是一种最坏情况下的保障措施,事实上,平时系统的运行可靠性都是相当高的,错误很少发生,因 此,在每次事务执行之前都检查其有效性显得代价太高——绝大多数的情况下这种耗时的检查是不必要的。我们不得不想另外一种办法来提高效率。

事 务存储点提供了一种机制,用于回滚部分事务。因此,我们可以不必在更新之前检查更新的有效性,而是预设一个存储点,在更新之后,如果没有出现错误,就继续 执行,否则回滚到更新之前的存储点。存储点的作用就在于此。要注意的是,更新和回滚代价很大,只有在遇到错误的可能性很小,而且预先检查更新的有效性的代 价相对很高的情况下,使用存储点才会非常有效。

使用.net框架编程时,你可以非常简单地定义事务存储点和回滚到特定的存储点。下面的语句定义了 一个存储点“NoUpdate”:

myTran.Save("NoUpdate");

当你在程序中创建同名的存储点时,新创建的存储点将 替代原有的存储点。

在回滚事务时,只需使用Rollback()方法的一个重载函数即可:

myTran.Rollback("NoUpdate");

下 面这段程序说明了回滚到存储点的方法和时机:

using System;

using System.Data;

using System.Data.SqlClient;

namespace Aspcn

{

  public class DbTran

  { 

file://执行事务处理

public void DoTran()

{

  file://建立连接并打开

  SqlConnection myConn=GetConn();

  myConn.Open();

  SqlCommand myComm=new SqlCommand();

  SqlTransaction myTran;

  file://创建一个事务

  myTran=myConn.BeginTransaction();

  file://从此开始,基于该连接的数据操作都被认为是事务的一部分

  file://下面绑定连接和事务对象

  myComm.Connection=myConn;

  myComm.Transaction=myTran;

  try

  {

myComm.CommandText="use pubs";

myComm.ExecuteNonQuery();

myTran.Save("NoUpdate");

myComm.CommandText="UPDATE roysched SET royalty = royalty * 1.10 WHERE title_id LIKE 'Pc%'";

myComm.ExecuteNonQuery();

file:// 提交事务

myTran.Commit();

  }

  catch(Exception err)

  {

file:// 更新错误,回滚到指定存储点

myTran.Rollback("NoUpdate");

throw new ApplicationException("事务操作出错,系统信息:"+err.Message);

  }

}

file:// 获取数据连接

private SqlConnection GetConn()

{

  string strSql="Data Source=localhost;Integrated Security=SSPI;user ;

  SqlConnection myConn=new SqlConnection(strSql);

  return myConn;

}

  }

  public class Test

  {

public static void Main()

{

  DbTran tranTest=new DbTran();

  tranTest.DoTran();

  Console.WriteLine("事务处理已经成功完成。");

  Console.ReadLine();

}

  }

}

很 明显,在这个程序中,更新无效的几率是非常小的,而且在更新前验证其有效性的代价相当高,因此我们无须在更新之前验证其有效性,而是结合事务的存储点机 制,提供了数据完整性的保证。