在數據庫工具類編寫的過程當中,對事務的處理操做想避免各個原子操做的事務對象賦值重複操做,想對外暴露的方法爲以下形式git
外部傳入的數據庫操做都使用委託統一打包,內部進行事務操做。咱們首先須要明白的是,數據庫事務操做在ADO.NET的編碼中的體現是,DbConnection爲同一個,DbCommand的Transaction爲同一個。數據庫
首先咱們須要識每個數據庫操做的上下文,是否在TransitionAction這個委託中,爲了簡單明瞭,在執行TransitionAction時開啓一個Task,取得當前線程的ThreadID做爲這個事務委託的惟一標識,並生成一個DbTransaction放入一個TransactionDic中,在SqlHelper執行類中執行SQL語句建立Connection時,取得當前的ThreadID去TransactionDic中查找,若是有對應的Transition則說明該SQL語句的執行是在一個事務中,Connection直接取Transition的數據庫鏈接,並給DbCommand的Transition對象賦值多線程
這個解決方案對於TransitionAction中執行方法類中的數據庫操做或其餘組合操做也是可行的,可是對於嵌套事務還須要進一步改進。app
好比我封裝好一個框架的工做流方法MethodA,自帶事物執行,可是須要與業務更新方法MethodB進行事物組合操做,上述方案並不能知足要求,須要咱們進行改進,判斷當前的事物TransitionAction是不是嵌套事務,即TransitionActionB實際是打包在TransitionActionA中的。在TransitionAction的DbTransaction添加的過程當中,咱們須要取到Task以外的ThreadID,這裏稱做爲RootThreadID,同時維護一個ConcurrentDictionary<string, List<string>> TransitionIDMapDic,用於維護RootThreadID與嵌套事務的ThreadID的關係,在建立Task時就能夠判斷當前的ThreadID是否在TransactionDic,存在就是嵌套事務,須要將當前的TransitionAction合併到Root事物中框架
TransactionManage 代碼工具
對外事物執行方法編碼
public bool ExecuteTransition(Action TransitionAction, out string ExceptionStr) { bool IsSuccess = true; ExceptionStr = string.Empty; string RootThreadID = Thread.CurrentThread.ManagedThreadId.ToString(); var TrabsitionTask = new Task<LocalTransactionResult>(() => { string TransitionID = Thread.CurrentThread.ManagedThreadId.ToString(); LocalTransactionResult Result = new LocalTransactionResult(); if (!TransactionManage.ContainsTransition(RootThreadID)) { using (DbConnection connection = DBExecute.CreateConnection(ConnectionString)) { connection.Open(); DbTransaction Transaction = connection.BeginTransaction(); TransactionManage.AddTransition(TransitionID, RootThreadID, Transaction, TransitionAction); try { TransactionManage.GetTransition(TransitionID).Execute(); Transaction.Commit(); } catch (System.Exception e) { Result.ExecuteStatus = false; Result.ExceptionMessage = e.Message; Transaction.Rollback(); } finally { Transaction.Dispose(); connection.Close(); connection.Dispose(); Transaction = null; TransactionManage.RemoveTransition(TransitionID); } return Result; } } else { //當前是嵌套事務,不執行,由根事務統一執行 TransactionManage.ContactTransition(TransitionID, RootThreadID, TransitionAction); Result.ExecuteStatus = true; Result.ExceptionMessage = string.Empty; return Result; } }); TrabsitionTask.Start(); TrabsitionTask.Wait(); IsSuccess = TrabsitionTask.Result.ExecuteStatus; ExceptionStr = TrabsitionTask.Result.ExceptionMessage; return IsSuccess; }
完整模塊代碼地址:https://gitee.com/grassprogramming/FastExecutorCore/tree/master/code/FastCore/FastCore/FastORMspa
注:我的感受使用線程的方式雖然很方便可是實際使用過程當中多線程可能會出現問題,後續會對執行類進行上下文對象的綁定改造線程