很多公司專屬應用程式系統,尤其是電商系統,事務的運用幾乎是不可避免的.事務的作用黃島主在這裡就不多說了,百度一下自有詳細資料...
這裡黃島主主要說的是,通常適當地使用事務不但可以保證執行的一致性,而且也降低了維護的工作負擔. 曾經一段時間因為沒有好好的運用事務特性,不得不結合作業記錄,訂單狀態..進行分析,之後加上諸如【訂單同步】,【價格同步】等可供人工幹預執行的按鈕.
出於之前對Visual studio內建的測試專案的瞭解,特意引入了類似的控制機制,對asp.net中應用sql事務進行了一定的封裝...目前使用中還挺順利的..如果有問題,歡迎討論和拍磚..
/// <summary> /// 功能簡介:SqlDBUtility的內部類,用於輔助控制批量的sql語句按照事務執行 /// 建立人:黃島主(taohuadaozhu007@qq.com) /// 聯絡地址:http://www.cnblogs.com/taohuadaozhu /// </summary> public class TransactionController { public class Command { private string commendText = ""; public string CommendText { get { return commendText; } } /// <summary> /// 期望的傳回值,影響行數 /// </summary> private int expectReturn = 0; /// <summary> /// 實際傳回值,影響行數 /// </summary> private int actualReturn = 0; /// <summary> /// true:嚴格要求實際傳回值==期望傳回值,false:要求實際傳回值>期望傳回值 /// </summary> private bool isRequestEqual = true; private string tipsOnError = ""; public string TipsOnError { get { return tipsOnError; } set { tipsOnError = value; } } /// <summary> /// 執行當前的Sql命令之後,實際返回的值,也就是影響行數 /// </summary> public int ActualReturn { get { return actualReturn; } set { actualReturn = value; } } /// <summary> /// 一個Sql命令處理對象 /// </summary> /// <param name="sCommendText">執行的sql語句</param> /// <param name="iExpectReturn">期望傳回值</param> /// <param name="bRequestEqual">true:嚴格要求實際傳回值==期望傳回值,false:要求實際傳回值>期望傳回值</param> public Command(string sCommendText, int iExpectReturn, bool bRequestEqual, string sTipsWhenError) { this.commendText = sCommendText; this.expectReturn = iExpectReturn; this.isRequestEqual = bRequestEqual; this.tipsOnError = sTipsWhenError; } /// <summary> /// 檢查是否執行成功 /// </summary> /// <returns></returns> public bool IsSuccess() { if (this.isRequestEqual) return (actualReturn == expectReturn); return (actualReturn > expectReturn); } } private List<Command> listCommand = null; public List<Command> ListCommand { get { if (listCommand == null) listCommand = new List<Command>(); return listCommand; } } public void Clear() { if (this.listCommand != null) this.listCommand.Clear(); } public bool IsSuccess() { if (listCommand == null) return false; for (int i = 0; i < listCommand.Count; i++) { if (listCommand[i].IsSuccess() == false) return false; } return true; } /// <summary> /// 獲得事務執行失敗處的資訊 /// </summary> /// <returns></returns> public string GetErrorPointMssage() { if (listCommand == null) return ""; for (int i = 0; i < listCommand.Count; i++) { if (listCommand[i].IsSuccess() == false) return listCommand[i].TipsOnError; } return ""; } }
上面的代碼,主要用於配置要一起執行(這些語句關聯同一個業務操作,可能涉及多個表,但需要保證是在同一個資料庫中)的sql命令對象Command,配置的過程中,注意指定每條sql語句預期的傳回值(影響的行數). 以及是否需要將預期的傳回值和實際的傳回值進行對比(也就是那個bool類型的bRequestEqual參數了). Command最後一個參數sTipsWhenError旨在指定如果失敗了,終止並復原sql命令後提示給使用者的錯誤提示內容..
具體結合ado.net進行檢測,復原,提交的代碼如下,黃島主在這裡提示各位,這個可能需要根據你自己的SqlDBHelp類進行略微調整...
/// <summary> /// 功能備忘:用事務的方式執行多條SQL語句 /// 建立人:黃島主(taohuadaozhu007@qq.com) /// 聯絡地址:http://www.cnblogs.com/taohuadaozhu /// </summary> /// <param name="trans_IsolationLevel">交易隔離等級設定,可以傳入:IsolationLevel.ReadCommitted</param> /// <returns></returns> public static void RunSQLWithTransaction(TransactionController theTransactionTool, IsolationLevel trans_IsolationLevel, string sSQLConnectstr) { if (theTransactionTool == null || theTransactionTool.ListCommand.Count == 0) return; using (SqlConnection conn = new SqlConnection(sSQLConnectstr)) { if (conn.State == ConnectionState.Broken || conn.State == ConnectionState.Closed) conn.Open(); using (SqlTransaction tran = conn.BeginTransaction(trans_IsolationLevel)) { using (SqlCommand sqlcm = new SqlCommand()) { if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken) conn.Open(); sqlcm.Connection = conn; sqlcm.Transaction = tran; try { for (int i = 0; i < theTransactionTool.ListCommand.Count; i++) { sqlcm.CommandText = theTransactionTool.ListCommand[i].CommendText; theTransactionTool.ListCommand[i].ActualReturn = sqlcm.ExecuteNonQuery(); if (theTransactionTool.ListCommand[i].IsSuccess() == false) { tran.Rollback(); sqlcm.Dispose(); if (conn.State == ConnectionState.Open) conn.Close(); break; } } if (theTransactionTool.IsSuccess()) { tran.Commit(); } } catch (Exception ex) { tran.Rollback(); IOManager.Log4Net.Log4NetTools.Warn(string.Format("執行事務的復原:" + ex.Message)); } finally { sqlcm.Dispose(); tran.Dispose(); if(conn.State==ConnectionState.Open) conn.Close(); } } } } }
好了,具體的代碼其實不重要,關鍵是向大家分享一下這個借鑒測試專案常用指令碼的事務輔助控制機制...