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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM