在資料庫工具類撰寫的程序中,對事務的處理操作想避免各個原子操作的事務物件賦值重復操作,想對外暴露的方法為如下形式
public bool ExecuteTransition(Action TransitionAction, out string ExceptionStr)
外部傳入的資料庫操作都使用委托統一打包,內部進行事務操作,我們首先需要明白的是,資料庫事務操作在ADO.NET的編碼中的體現是,DbConnection為同一個,DbCommand的Transaction為同一個,

?
首先我們需要識每一個資料庫操作的背景關系,是否在TransitionAction這個委托中,為了簡單明了,在執行TransitionAction時開啟一個Task,取得當前執行緒的ThreadID作為這個事務委托的唯一標識,并生成一個DbTransaction放入一個TransactionDic中,在SqlHelper執行類中執行SQL陳述句創建Connection時,取得當前的ThreadID去TransactionDic中查找,如果有對應的Transition則說明該SQL陳述句的執行是在一個事務中,Connection直接取Transition的資料庫連接,并給DbCommand的Transition物件賦值

?
這個解決方案對于TransitionAction中執行方法類中的資料庫操作或其他組合操作也是可行的,但是對于嵌套事務還需要進一步改進,
比如我封裝好一個框架的作業流方法MethodA,自帶事物執行,但是需要與業務更新方法MethodB進行事物組合操作,上述方案并不能滿足要求,需要我們進行改進,判斷當前的事物TransitionAction是否是嵌套事務,即TransitionActionB實際是打包在TransitionActionA中的,在TransitionAction的DbTransaction添加的程序中,我們需要取到Task之外的ThreadID,這里稱作為RootThreadID,同時維護一個ConcurrentDictionary<string, List<string>> TransitionIDMapDic,用于維護RootThreadID與嵌套事務的ThreadID的關系,在創建Task時就可以判斷當前的ThreadID是否在TransactionDic,存在就是嵌套事務,需要將當前的TransitionAction合并到Root事物中

?
TransactionManage 代碼
public class TransactionManage { private static ConcurrentDictionary<string, LocalTransaction> TransactionDic = new ConcurrentDictionary<string, LocalTransaction>(); private static ConcurrentDictionary<string, List<string>> TransitionIDMapDic = new ConcurrentDictionary<string, List<string>>(); public static void AddTransition(string TransitionID,string RootThreadID, DbTransaction Transition,Action TransitionAction) { LocalTransaction LT = new LocalTransaction(); LT.RootThreadID = RootThreadID; LT.TransitionID = TransitionID; LT.Transition = Transition; //執行串列增加Action LT.AddTransitionAction(TransitionAction); TransactionDic.TryAdd(TransitionID, LT); //增加事務根執行緒ID與嵌套事務相關事務ID TransitionIDMapDic.TryAdd(RootThreadID, new List<string>() { TransitionID }); } public static void ContactTransition(string TransitionID, string RootThreadID,Action TransitionAction) { LocalTransaction LT = TransactionDic[RootThreadID]; if (!TransactionDic.ContainsKey(LT.RootThreadID)) { LT.TransitionID = TransitionID; //執行串列增加Action LT.AddTransitionAction(TransitionAction); TransactionDic.TryAdd(TransitionID, LT); //增加事務根執行緒ID與嵌套事務相關事務ID List<string> TransitionIDS = TransitionIDMapDic[LT.RootThreadID]; TransitionIDS.Add(TransitionID); TransitionIDMapDic[LT.RootThreadID] = TransitionIDS; } else { ContactTransition(TransitionID, LT.RootThreadID, TransitionAction); } } public static string GetRootID(string TransitionID) { LocalTransaction LT = TransactionDic[TransitionID]; if (!TransactionDic.ContainsKey(LT.RootThreadID)) { return LT.RootThreadID; } else { return GetRootID(LT.RootThreadID); } } public static LocalTransaction GetTransition(string TransitionID) { LocalTransaction LT = null; TransactionDic.TryGetValue(TransitionID, out LT); return LT; } public static bool ContainsTransition(string TransitionID) { return TransactionDic.ContainsKey(TransitionID); } public static void RemoveTransition(string TransitionID) { string RootID = GetRootID(TransitionID); List<string> TransitionIDList = null; TransitionIDMapDic.TryRemove(RootID, out TransitionIDList); foreach (string TransitionIDItem in TransitionIDList) { LocalTransaction LT = null; TransactionDic.TryRemove(TransitionIDItem, out LT); } }
對外事物執行方法
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/FastORM
注:個人感覺使用執行緒的方式雖然很方便但是實際使用程序中多執行緒可能會出現問題,后續會對執行類進行背景關系物件的系結改造
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/80526.html
標籤:C#
