事務只是一種最壞情況下的保障措施,事實上,平時系統的運行可靠性都是相當高的,錯誤很少發生,因此,在每次事務執行之前都檢查其有效性顯得代價太高——絕大多數的情況下這種耗時的檢查是不必要的。我們不得不想另外一種辦法來提高效率。
事務存儲點提供了一種機制,用於回滾部分事務。因此,我們可以不必在更新之前檢查更新的有效性,而是預設一個存儲點,在更新之後,如果沒有出現錯誤,就繼續執行,否則回滾到更新之前的存儲點。存儲點的作用就在於此。要注意的是,更新和回滾代價很大,只有在遇到錯誤的可能性很小,而且預先檢查更新的有效性的代價相對很高的情況下,使用存儲點才會非常有效。
使用.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 id=sa;passWord=";
SqlConnection myConn=new SqlConnection(strSql);
return myConn;
}
}
public class Test
{
public static void Main()
{
DbTran tranTest=new DbTran();
tranTest.DoTran();
Console.WriteLine("事務處理已經成功完成。");
Console.ReadLine();
}
}
}
很明顯,在這個程序中,更新無效的幾率是非常小的,而且在更新前驗證其有效性的代價相當高,因此我們無須在更新之前驗證其有效性,而是結合事務的存儲點機制,提供了數據完整性的保證。