我的ORM之五-- 事务
单库事务与分布式事务
单库事务: 性能更好,应用于一个数据库时的场景,当数据库发生变化,如拆分为多个服务器,代码需要修改。
分布式事务:性能相对较差,但有更大的适用场景。当数据库发生变化,如拆分为多个服务器,代码可能不需要修改。
由于事务会引起资源争抢,互联网平台,越来越趋向无事务处理,追求极致的性能。
分布式事务
using (ransactionScope scope = new TransactionScope()) { //to do something scope.Complete(); }
单库事务
在实际应用中,我更倾向于单库事务。用法也很像分布式事务,可以嵌套。
string errorMsg = dbr.表1.ExecTransaction(()=> { if( 表1操作失败) return "表1失败"; if( 表2操作失败) return "表2失败"; if( 表3操作失败) return "表3失败"; var msg = 调用其它单库事务方法; if( msg.HasValue() ) return msg; return ""; });
在 ExecTransaction 方法中,返回空值或空字符串,表示成功。 如果返回错误信息,则事务回滚。
具体实现方法:(需根据项目修改)
实现思想:在执行事务前,先使用 lock 锁住某个表示该表的对象。使其它使用该表的事务在数据库外排队,防止死锁。
public static string ExecTransaction(this RuleBase rule, Func<string> func) { return ExecTransaction(rule, new LockObjectEnum(), func); } /// <summary> /// 单库事务安全执行方法 /// </summary> /// <param name="rule"></param> /// <param name="func"></param> /// <returns></returns> public static string ExecTransaction(this RuleBase rule, LockObjectEnum LockObj, Func<string> func) { var group = rule.GetGroupName().AsString(me.CorpID.ToString()); if (LockObj.HasValue() == false) { group.MySplit('_').All(g => { var e = g.ToEnum<LockObjectEnum>(); if (e > 0) { LockObj = e; return false; } return true; }); } var ret = string.Empty; lock (rule.GetLockObject()) { For2Recusion(LockObj.GetEnumList(), () => { ret = _execTransactionWithoutLock(rule, func); }); } return ret; } private static void For2Recusion(LockObjectEnum[] objs, Action act, int index = 0) { if (index < objs.Length) { lock (MyHelper.GetLockObject("ExecTransaction." + objs[index].ToString())) { For2Recusion(objs, act, index + 1); } } else { act(); } } private static string _execTransactionWithoutLock(RuleBase rule, Func<string> func) { var msg = string.Empty; if (dbo.CurrentScope != null && dbo.CurrentScope.Transaction != null) { try { msg = func(); if (msg.HasValue()) { return msg; } } catch (Exception e) { msg = e.Message; throw; } return msg; } using (var conn = rule.GetDbConnection()) { msg = dbo.Open(conn, () => { var tran = conn.BeginTransaction(); using (var scope = new MyOqlConfigScope(tran)) { try { msg = func(); if (msg.HasValue()) { tran.Rollback(); return msg; } tran.Commit(); } catch (Exception e) { msg = e.Message; if (conn.State != ConnectionState.Closed) { tran.Rollback(); } throw; } return msg; } }); } return msg; }
作者:NewSea 出处:http://newsea.cnblogs.com/
QQ,MSN:iamnewsea@hotmail.com 如无特别标记说明,均为NewSea原创,版权私有,翻载必纠。欢迎交流,转载,但要在页面明显位置给出原文连接。谢谢。 |