在数据库工具类编写的过程中,对事务的处理操作想避免各个原子操作的事务对象赋值重复操作,想对外暴露的方法为如下形式

   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

注:个人感觉使用线程的方式虽然很方便但是实际使用过程中多线程可能会出现问题,后续会对执行类进行上下文对象的绑定改造

最新文章

  1. [Unity3D] Normal map、Diffuse map 和 Speculer map
  2. WebBrowser处理AJAX生成的网页内容!
  3. Mybatis的缺陷
  4. matlab中的卷积——filter,conv之间的区别
  5. uC/OS-II全局变量定义
  6. JavaEE面试题库
  7. kissy使用注意事项
  8. Ubuntu 使用top/free查看内存占用大的原因
  9. Android 中常用代码片段
  10. Ark组件设计随想(一)
  11. 建立一个属于自己的AVR的RTOS
  12. 4 安装MPush
  13. TypeError: Error #1034: 强制转换类型失败:无法将 &quot;&quot; 转换为 Array。
  14. MySql实现远程访问配置
  15. CSS实现背景透明,文字不透明(兼容所有浏览器)
  16. 003.MongoDB主要概念
  17. varchar字数
  18. android iOS 编码问题害死人!
  19. 用@resource注解方式完成属性装配
  20. 编译安装MariaDB-10.0.21

热门文章

  1. 【Nginx入门系列】第一章 手把手带你搭建Nginx服务器
  2. C++ 中库函数bsearch的简单研究(含示例)
  3. 使用Java封装一个DBUtils类(反射)
  4. 「C++ 篇」答应我,别再if/else走天下了可以吗
  5. Loj 6002 最小路径覆盖(最大流)
  6. ant编译solr源码生成eclipse项目,解决一直resolve,一直[ivy:retrieve]的问题
  7. 微信小程序如何添加新的icon图标
  8. 大数据篇:Zookeeper
  9. Ubuntu 18.04下用户的创建、修改权限及删除用户的方法
  10. 高级安全Windows防火墙概述以及最佳实践