使用PetaPoco结合注入实现业务级事务
2013-09-18 14:01
295 查看
使用PetaPoco结合注入实现业务级事务
PetaPoco是一个轻量级ORM,我的MVC项目中使用它结合Repository模式,依靠Unity的生命周期管理对象,保证请求/线程级别的数据上下文单例,并使用锁和计数实现业务级事务。下文代码依个人理解实现,谬误请不吝指正。例行IUnitOfWork:
public interface IUnitOfWork { void Begin(); void Commit(); void Rollback(); }
仓库上下文核心:
1 public class PetaPocoUnitOfWork : IUnitOfWork 2 { 3 private const String _dbName = "Northwind"; 4 private Boolean _requireAbort = false; 5 private Int32 _transactionDepth = 0; 6 private Object _transactionLock = new Object(); 7 8 public Database DBContext { get; protected set; } 9 10 public Guid Id { get; private set; } 11 12 public PetaPocoUnitOfWork() 13 { 14 Id = Guid.NewGuid(); 15 DBContext = new Database(_dbName); 16 } 17 18 public void Begin() 19 { 20 lock (_transactionLock) 21 { 22 if (_transactionDepth == 0) 23 { 24 DBContext.BeginTransaction(); 25 } 26 _transactionDepth++; 27 } 28 29 } 30 31 public void Commit() 32 { 33 lock (_transactionLock) 34 { 35 _transactionDepth--; 36 if (_transactionDepth == 0) 37 { 38 try 39 { 40 DBContext.CompleteTransaction(); 41 } 42 catch 43 { 44 _transactionDepth++; 45 _requireAbort = true; 46 throw; 47 } 48 } 49 } 50 } 51 52 public void Rollback() 53 { 54 lock (_transactionLock) 55 { 56 _transactionDepth--; 57 if (_transactionDepth == 0) 58 { 59 DBContext.AbortTransaction(); 60 _requireAbort = false; 61 } 62 } 63 } 64 65 public void Dispose() 66 { 67 if (_requireAbort) 68 { 69 DBContext.AbortTransaction(); 70 } 71 DBContext.Dispose(); 72 } 73 }
在应用层对Unity注入的IUnitOfWork调用Begin()即开启事务,对于嵌套事务变量_transactionDepth++记录事务深度,Commit()与Rollback()时_transactionDepth--,保证业务中事务只开启与提交一次。如有应用层ITradeService及实现:
1 public abstract class ApplicationService { 2 public IUnitOfWork Context { get; private set; } 3 4 public ApplicationService(IUnitOfWork context) { 5 Context = context; 6 } 7 } 8 9 public interface ITradeService { 10 void SubmitOrder(Order model); 11 } 12 13 public class TradeService : ApplicationService, ITradeService { 14 private readonly IOrderRepository _orderRepository; 15 private readonly IOrderDetailRepository _orderDetailRepository; 16 17 public TradeService( 18 IUnitOfWork context, 19 IOrderRepository orderRepository, 20 IOrderDetailRepository orderDetailRepository) 21 : base(context) { 22 _orderRepository = orderRepository; 23 _orderDetailRepository = orderDetailRepository; 24 } 25 26 void SubmitOrder(OrderDTO model){ 27 //do something, like null reference check etc.. 28 29 Order order = //... some logic 30 OrderDetail orderDetail = //as above 31 32 try { 33 Context.Begin(); 34 35 _orderRepository.Update(order); 36 _orderDetailRepository.Update(orderDetail); 37 //could be more complex 38 39 Context.Commit(); 40 } 41 catch { 42 Context.Rollback(); 43 throw; 44 } 45 } 46 }
当顾客提交订单时,Context.Begin()开启一个事务锁,由于Unity的生命周期管理,当前线程内的数据上下文实例是同一个对象,故能够保证事务。当事务发生嵌套时,事务深度的解决方法发生作用,比如以可测试性的提高截取部分代码示例:
[TestClass] public class AccountServiceTest { [TestMethod] public void TradeServiceTest_SubmitOrder() { IUnitOfWork context = ... //some initialize logic OrderDTO model = ... //as above TradeService service = //as above context.Begin(); service.SubmitOrder(); context.Rollback(); ///... etc } }
相关文章推荐
- 使用PetaPoco结合注入实现业务级事务
- Android开发ViewPager和Fragment结合使用实现新闻类app基本框架(一)
- C#中使用COM+实现事务控制
- 使用事务实现--转账问题:从0001账户转1000块到0002账户。打开"隐式事务":设置为开,删除表中数据,回滚!(默认情况为关,如果打开了则不自动提交,学要手动提交)
- ViewPager+Fragment的结合使用,实现QQ界面的理解
- Spring学习笔记(18)----使用Spring配置文件实现事务管理
- OpenStack镜像如何使用Config Drive实现元数据注入
- Yii1.0 使用thickbox结合独立控制器实现图片上传
- 扩展ASP.NET MVC三层框架并使用StructureMap实现依赖注入2-Repository层的实现
- Spring中使用事务搭建转账环境方法二 相对简便的注解方法 ——配置文件注入对象属性需要setter方法 注解方法,不需要生成setter方法
- 使用事务与锁,实现一个用户取过的数据不被其他用户取
- spring中的切点(AOP)和事务(ACID)的结合使用 spring.xml的配置
- MySQL 的异常与事务结合的使用方法。并带自动回滚!
- 使用volley并结合HttpClient实现上传文件
- 使用 Vue.js 结合bootstrap 实现的分页控件
- 使用spring的aop实现拦截action后出现依赖注入为空的问题
- 实现带快速导航的ListView(自定义View和自定义ViewGroup的结合),可直接使用和修改使用
- ASP.Net MVC5 使用Unity 实现依赖注入
- JS与HTML结合使用marquee标签实现无缝滚动效果代码
- 使用Sqlserver事务发布实现数据同步