zoukankan      html  css  js  c++  java
  • 使用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
        }
    }
  • 相关阅读:
    SQL的四种连接(内连接,外连接)
    MySQL连表操作之一对多
    [转]Mysql连表之多对多
    Hibernate笔记二
    Hibernate框架报错:org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.mikey.hibernate.domain.Person.pid
    Hibernate框架:org.hibernate.exception.SQLGrammarException: Cannot open connection at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java92)
    [转]网络编程三要素
    Hibernate笔记一
    JavaScript高级特征之面向对象笔记
    Myeclipse创建HTML文件中文显示乱码问题
  • 原文地址:https://www.cnblogs.com/Jusfr/p/3327948.html
Copyright © 2011-2022 走看看