使用PetaPoco结合注入实现业务级事务
2013-09-18 10:19
274 查看
PetaPoco是一个轻量级ORM,我的MVC项目中使用它结合Repository模式,依靠Unity的生命周期管理对象,保证请求/线程级别的数据上下文单例,并使用锁和计数实现业务级事务。下文代码依个人理解实现,谬误请不吝指正。
例行IUnitOfWork:
仓库上下文核心:
在应用层对Unity注入的IUnitOfWork调用Begin()即开启事务,对于嵌套事务变量_transactionDepth++记录事务深度,Commit()与Rollback()时_transactionDepth--,保证业务中事务只开启与提交一次。如有应用层ITradeService及实现:
当顾客提交订单时,Context.Begin()开启一个事务锁,由于Unity的生命周期管理,当前线程内的数据上下文实例是同一个对象,故能够保证事务。当事务发生嵌套时,事务深度的解决方法发生作用,比如以可测试性的提高截取部分代码示例:
例行IUnitOfWork:
public interface IUnitOfWork { void Begin(); void Commit(); void Rollback(); }
仓库上下文核心:
public class PetaPocoUnitOfWork : IUnitOfWork { private const String _dbName = "Northwind"; private Boolean _requireAbort = false; private Int32 _transactionDepth = 0; private Object _transactionLock = new Object(); public Database DBContext { get; protected set; } public Guid Id { get; private set; } public PetaPocoUnitOfWork() { Id = Guid.NewGuid(); DBContext = new Database(_dbName); } public void Begin() { lock (_transactionLock) { if (_transactionDepth == 0) { DBContext.BeginTransaction(); } _transactionDepth++; } } public void Commit() { lock (_transactionLock) { _transactionDepth--; if (_transactionDepth == 0) { try { DBContext.CompleteTransaction(); } catch { _transactionDepth++; _requireAbort = true; throw; } } } } public void Rollback() { lock (_transactionLock) { _transactionDepth--; if (_transactionDepth == 0) { DBContext.AbortTransaction(); _requireAbort = false; } } } public void Dispose() { if (_requireAbort) { DBContext.AbortTransaction(); } DBContext.Dispose(); } }
在应用层对Unity注入的IUnitOfWork调用Begin()即开启事务,对于嵌套事务变量_transactionDepth++记录事务深度,Commit()与Rollback()时_transactionDepth--,保证业务中事务只开启与提交一次。如有应用层ITradeService及实现:
public abstract class ApplicationService { public IUnitOfWork Context { get; private set; } public ApplicationService(IUnitOfWork context) { Context = context; } } public interface ITradeService { void SubmitOrder(Order model); } public class TradeService : ApplicationService, ITradeService { private readonly IOrderRepository _orderRepository; private readonly IOrderDetailRepository _orderDetailRepository; public TradeService( IUnitOfWork context, IOrderRepository orderRepository, IOrderDetailRepository orderDetailRepository) : base(context) { _orderRepository = orderRepository; _orderDetailRepository = orderDetailRepository; } void SubmitOrder(OrderDTO model){ //do something, like null reference check etc.. Order order = //... some logic OrderDetail orderDetail = //as above try { Context.Begin(); _orderRepository.Update(order); _orderDetailRepository.Update(orderDetail); //could be more complex Context.Commit(); } catch { Context.Rollback(); throw; } } }
当顾客提交订单时,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结合注入实现业务级事务
- 使用Java原生代理实现数据注入
- springboot配置文件中使用配置信息自定义注入哪一个类名(比如多个类实现一个接口,使用resource(name=${配置文件的key}”))
- 使用Spring 2.0 新特性实现声明式事务管理-基于XML Schema
- Vue2.0与 [百度地图] 结合使用———vue+webpack+axios+百度地图实现组件之间的通信
- 使用Python的Django框架结合jQuery实现AJAX购物车页面
- 时间序列数据库KDB 与Java结合使用介绍 -- 3 基于KDB JDBC的写入实现
- 结合使用 volatile 和 synchronized 实现 “开销较低的读-写锁”
- Yii1.0 使用thickbox结合独立控制器实现图片上传
- Spring中使用事务搭建转账环境方法二 相对简便的注解方法 ——配置文件注入对象属性需要setter方法 注解方法,不需要生成setter方法
- 使用EditText+ListView并结合TextWatcher实现输入关键字筛选数据
- 使用volley并结合HttpClient实现上传文件
- maven profile 结合spirng注解使用——实现配置文件最小化
- 依赖注入 - 如何使用反射和注解实现简单的依赖注入
- SpringMVC 使用注解注入生成接口实现类对象
- Jquery结合Ajax和Web服务使用三层架构实现无刷新分页
- Gitlab和Sourcetree结合使用实现代码管理
- 使用JOTM实现分布式事务管理(多数据源)
- MySql使用存储过程实现事务的提交或者回滚
- TransactionScope使用(一)——简单的实现事务处理