在数据库工具类编写的过程当中,对事务的处理操做想避免各个原子操做的事务对象赋值重复操做,想对外暴露的方法为以下形式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
注:我的感受使用线程的方式虽然很方便可是实际使用过程当中多线程可能会出现问题,后续会对执行类进行上下文对象的绑定改造线程