您的位置:首页 > 其它

使用PetaPoco结合注入实现业务级事务

2013-09-18 10:19 274 查看
PetaPoco是一个轻量级ORM,我的MVC项目中使用它结合Repository模式,依靠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
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐