您的位置:首页 > 其它

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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐