使用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
    }
}

 

posted @ 2013-09-18 10:19  Jusfr  阅读(4751)  评论(7编辑  收藏  举报