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

使用PetaPoco结合注入实现业务级事务的更多相关文章
- sql服务器第5级事务日志管理的阶梯:完全恢复模式下的日志管理
sql服务器第5级事务日志管理的阶梯:完全恢复模式下的日志管理 原文链接http://www.sqlservercentral.com/articles/Stairway+Series/73785/ ...
- spring注解实现业务层事务管理,当业务层自调用时,事务失效问题解决
前些日子一朋友在需要在目标对象中进行自我调用,且需要实施相应的事务定义,且网上的一种通过BeanPostProcessor的解决方案是存在问题的.因此专门写此篇帖子分析why. 1.预备知识 aop概 ...
- JDBC基础:JDBC快速入门,JDBC工具类,SQL注入攻击,JDBC管理事务
JDBC基础 重难点梳理 一.JDBC快速入门 1.jdbc的概念 JDBC(Java DataBase Connectivity:java数据库连接)是一种用于执行SQL语句的Java API,可以 ...
- spring项目中service方法开启线程处理业务的事务问题
1.前段时间在维护项目的时候碰到一个问题,具体业务就是更新已有角色的资源,数据库已更新,但是权限控制不起效果,还是保留原来的权限. 2.排查发现原有的代码在一个service方法里有进行资源权限表的更 ...
- servlet注入service业务bean
项目中用到spring容器来管理业务bean,在servlet中就收到前台传递来的请求参数后,调用业务bean,老是出错 部门代码如下 <span style="font-size:1 ...
- c# 业务层事务
步骤: 1.先添加System.Transactions.dll的引用 2.使用System.Transactions命名空间下的类 实例: using (TransactionScope scope ...
- Java之事务的基本应用
基本介绍 事务是数据一致性最基本的保证,也就是说一个事务中的操作要么都成功,要么都失败,不允许部分成功.我们常说的事务就是jdbc事务,当然Java中还有其他事务,并且在使用jdbc事务有很多注意点, ...
- 如何优化MySQL千万级大表
很好的一篇博客,转载 如何优化MySQL千万级大表 原文链接::https://blog.csdn.net/yangjianrong1985/article/details/102675334 千万级 ...
- Web基础之Spring AOP与事务
Spring之AOP AOP 全程Aspect Oriented Programming,直译就是面向切面编程.和POP.OOP相似,它也是一种编程思想.OOP强调的是封装.继承.多态,也就是功能的模 ...
随机推荐
- C++调用一个成员函数的需求this指针的情况
1.虚成员函数,因为需要this展望虚表指针的指针 2.在数据成员的操作部件的功能 #include "stdafx.h" #include <iostream> #i ...
- Windows RPC
转载 Windows RPC Demo实现 本文参考并整理以下相关文章 1. <远程过程调用> -百度百科 2. <RPC 编程> -http://www.ibm.com/de ...
- UVa 10533 - Digit Primes
题目:输出给定区间中,本身是素数,而且这个数的各位之和也是素数的数(称为位素数)的个数. 分析:数论.首先利用筛法,求出1000000内的全部的素数:然后在利用生成的素数表, 推断每一个数是不是各位之 ...
- 【设计模式】Abstract Factory模式
抽象工厂模式是工厂方法模式的进一步强化.当工厂函数仅仅须要产生一种类型的产品(全部产品都继承自同一抽象基类)时,使用工厂方法模式就可以. 可是.当用户程序须要创建多种类型的产品,而这些产品又有一定的内 ...
- STL该反应堆运行
首先来看全然二叉树的定义: 若设二叉树的深度为h,除第 h 层外,其他各层 (1-h-1) 的结点数都达到最大个数,第 h 层全部的结点都连续集中在最左边,这就是全然二叉树.而将一维数组视为全然二叉树 ...
- 【.NET特供-第三季】ASP.NET MVC系列:MVC与三层图形对照
近期在开发小组在研究:BS项目中是利用'MVC框架'还是继续沿用'三层'的问题. 由于曾经的.NET项目大多数都是利用三层开发的,所以大多数人都可以对三层进行熟练地运用.而项目的開始我们也曾听说过MV ...
- boost进程间通信经常使用开发一篇全(消息队列,共享内存,信号)
本文概要: 敏捷开发大家想必知道并且评价甚高,缩短开发周期,提高开发质量.将大project独立为不同的小app开发,整个开发过程,程序可用可測,所以提高了总体的质量.基于这样的开发模式和开发理念,进 ...
- 聊聊单元測试(一)——EasyMock
一.单元測试是保证软件质量的重要方法. 单元測试是对系统中某个模块功能的验证,但我们总会遇到这样那样的问题,导致測试代码非常难编写.最直接的一个原因便是强耦合关系,被測试者依赖一些不easy构造,比較 ...
- getch()、getche()和getchar()函数
原文:getch().getche()和getchar()函数 getch().getche()和getchar()函数(1) getch()和getche()函数 这两个函数都是从键盘上读入一个字符 ...
- 关于android中sqllite对时间的操作
sql 中有时间的类型,date,time,datetime,方便关于记录的维护,下面一个demo演示怎么在每条记录中默认增加时间 源码下载地址 http://www.codes51.com/code ...