先来上一段MSDN里 的介绍
类提供一个简单方法,通过这一方法,您不必与事务本身交互,即可将代码块标记为参与某个事务。事务范围可以自动选择和管理环境事务。由于它易于使用并且效率很高,因此建议您在开发事务应用程序时使用 TransactionScope 类。
此外,您不必显式向事务登记资源。任何 资源管理器(例如 SQL Server 2005)都可以检测到该范围创建的环境事务的存在并自动登记。
更详细一点的,可以看下面这个网页
http://idior.cnblogs.com/archive/2005/08/15/214300.html
为什么不用自带的"
"
先简单说说(因为我主要想说他和缺点)
的优点:
一:使用起来比较方便.TransactionScope可以实现隐式的事务,使你可以在写数据访问层代码的时候不用
考虑到事务,而在业务层的控制事务.关于这点,可以看Petshop4.0.
二:可以实现分布式事务,比如跨库或MSMQ. 关于这个偶就不用多说了,哈哈.地球人都知道!
好了,说完了好处,来,开始批斗了....蹲地上,唱东方红....
缺点
一:性价比不高.比如,你只是在"Scope"里控制一个库的事务.用"TransactionScope"就有点TMD(请原谅我这
么激动,实现是太不值得了)的浪费了.
二:一般情况下只要你使用"TransactionScope",都要配置MSDTC,要配防火墙,要开139(记不清了,貌似是这个
)端口.问过专业大牛,人家说了,这个端口不可以更改,日(对不起,我太生气了..)
基于上面这二个问题,偶们决定"Scope"再好,偶们也不用了(拼了),但是,偶们还想实现那种类似于隐式的
事务代码(这个太勾引人了).于是,偶们搞出了这个自己的"Scope"(注意,偶这个只能实现数据库的事务而且不是分布式的,当然不用开端口,也基本无性能问题).
实现原理
偶是不指望实现自己的事务管理器来实现自己"Scope"了,于是偶想到了这个办法分三步实现.
一.在实例化自己的"Scope"时,记一个事务标志位.
二.在访问数据库时,查看有没有事务标志位.如果有,从"Scope"取一个数据库事务.将这个事务赋给DBCommand,并将这个事务和连接记下来,如果下次有同样的连接字符串请示事务,就将这个事务发给他.
三.在我们的"Scope"被Dispose时,判断用户调没调用Complete方法,如果调了,说明用户提交了事务,没调就说明事务回滚(和"TransactionScope"是一样的).然后提交或回滚所有的DBTransaction.
根据上面的实现,偶们需要控制用户数据访问方式,也就是说让他们用偶们提供的数据访问代码,才能实现我们自己的"Scope".于是,偶想到了企业库.偶用的是企业库3.1版的
下面开始放代码
先放实现后的调用代码,是不是和"TransactionScope"很像?
DJTransactionScope (偶这个项目是DJ开头的,DJ呵呵)
{
//要确保对支持事务的资源的登记放在此范围内,如数据库资源的打开
A a=new A();
a.method();
..
B b = new b();
b.method();
scope.comlete()
}
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Web;
using System.Threading;
namespace DJ.Framework.Transaction
{
public class DJTransactionScope : IDisposable
{
/// <summary>
/// 标志位,标志用户是不是提交了事务
/// </summary>
private bool isCompleted = false;
/// <summary>
/// 存放已加入的事务的Connection的
/// </summary>
private Dictionary<String, ConnAndTranPaire> transactionPool = new Dictionary<string, ConnAndTranPaire>();
/// <summary>
/// 用来存放WinFrom程序中的事务
/// </summary>
[ThreadStatic]
private static DJTransactionScope currentScope;
/// <summary>
/// 取得当前事务
/// </summary>
public static DJTransactionScope Current
{
get
{
//如果这不是一个Web项目
if (HttpContext.Current == null)
{
return currentScope;
}
else
{
//Web项目的话,就把事务标志放到HttpContext中
HttpContext context = HttpContext.Current;
return context.Items["CurrentTransactionScope"] as DJTransactionScope;
}
}
private set
{
if (HttpContext.Current == null)
{
currentScope = value;
}
else
{
HttpContext context = HttpContext.Current;
if (context.Items.Contains("CurrentTransactionScope"))
context.Items["CurrentTransactionScope"] = value;
else
context.Items.Add("CurrentTransactionScope", value);
}
}
}
private Guid scopeID = Guid.NewGuid();
/// <summary>
/// 事务ID
/// </summary>
public Guid ScopeID
{
get
{
return scopeID;
}
}
/// <summary>
/// 构造方法
/// </summary>
public DJTransactionScope()
{
//如果当前没有起动事务,就记下此标志
if (Current == null)
{
Current = this;
}
}
/// <summary>
/// 调用此方法,将会在代码段结束后提交事务
/// </summary>
public void Complete()
{
//记录用户的提示
isCompleted = true;
}
/// <summary>
/// 加入当前事务
/// </summary>
/// <param name="database"></param>
/// <returns></returns>
public DbTransaction JoinTransaction(Database database)
{
if (transactionPool.ContainsKey(database.ConnectionStringWithoutCredentials))
{
return transactionPool[database.ConnectionStringWithoutCredentials].Transaction;
}
else
{
DbConnection dbconnection = database.CreateConnection();
dbconnection.Open();
DbTransaction dbTransaction = dbconnection.BeginTransaction();
ConnAndTranPaire paire = new ConnAndTranPaire();
paire.Connection = dbconnection;
paire.Transaction = dbTransaction;
transactionPool.Add(database.ConnectionStringWithoutCredentials, paire);
return paire.Transaction;
}
}
public override bool Equals(object obj)
{
if (obj is DJTransactionScope)
{
DJTransactionScope scope = obj as DJTransactionScope;
return (scope.scopeID == this.scopeID);
}
return false;
}
public override int GetHashCode()
{
return scopeID.GetHashCode();
}
IDisposable 成员
private void RemoveTransaction()