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


    使用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
        }
    }
    复制代码
     
     
     
    标签: .Net
  • 相关阅读:
    大数据笔记
    关于服务器编程的笔记
    [转] IPC之管道、FIFO、socketpair
    一些公司链接
    Delphi 通过字符串实例化类
    Delphi根据字符串实例化对象
    Class-reference types 类引用类型--快要失传的技术
    GETCLASS与REGISTERCLASS的应用一例
    Delphi XE增强的RTTI妙用--动态创建包中的窗口类
    Delphi2010的RTTI增强
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3328306.html
Copyright © 2020-2023  润新知