System.Transactions深入了解

System.Transactions框架包含了一个称为LTM(Lightweight Transaction Manager)的TM,它隐式的将连接登记于事务中,从内部来看,是由ITransaction Transaction.Current{get;set}静态属性来完成的。ITransaction接口提供了多个方法,让RM能够将它的数据源等级于事务中。如果Transaction.Current属性返回一个事务,那么RM的启用代码就只需将RM本身进行登记。当然创建TransactionScope的实例将会执行事务的内部创建,而通过Trasaction.Current属性就可以得到这个创建的事务。

显示实现事务

 直接使用CommittableTransaction,但是必须要显示的注册事务

代码
   
     
protected void Page_Load( object sender, EventArgs e)
{
string connStr1 = " server=HEAIPING-PC;uid=sa;pwd=sa;database=DemoDB " ;
string connStr2 = " server=HEAIPING-PC;uid=sa;pwd=sa;database=DemoDB2 " ; // 另外一个数据库

string strSql1 = " delete from demoTb1 " ;
string strSql2 = " insert into DB2Tb values('222') " ;
try
{
CommittableTransaction tx
= new CommittableTransaction();
// 对第一个数据库的操作
using (SqlConnection conn1 = new SqlConnection(connStr1))
{
conn1.Open();
// 注册事务
conn1.EnlistTransaction(tx);
SqlCommand cmd
= new SqlCommand(strSql1, conn1);
cmd.ExecuteNonQuery();
}
// 对第二个数据库的操作
using (SqlConnection conn2 = new SqlConnection(connStr2))
{
conn2.Open();
// 注册事务
conn2.EnlistTransaction(tx);
SqlCommand cmd
= new SqlCommand(strSql2, conn2);
cmd.ExecuteNonQuery();
}
tx.Commit();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}

}

其实这个实现的功能和TransactionScope的功能是一样的,其实如果不是为了特定的异步上下文中使用这种显示的实现。其他时候没有必要这样子做的。

在多个线程中执行一个事务

  在多线程应用程序中,由Transaction.Current静态属性所定义的当前事务只对创建它的线程有效。这意味着由线程A创建的事务在执行过程中,另外一个线程B通过这个属性获得的将会是一个空置。如果希望让多个线程参与同一个事务,那么需要为其他线程提供原事务的依赖事务(dependant transaction)。可以通过可以通过IDependantTransaction ITransaction.DependentClone(bool)方法获得依赖事务。IDependantTransaction接口扩展了ITransaction的方法,在其基础上增加了Complete()方法。这个方法用于向父事务指明:依赖事务已经正确地完成了任务。如果所有依赖事务都调用了Complete方法,而且父事务也成功了,那么就可以对事务调用Commit方法了。

  为了让避免Complete和Commit方法调用之间的同步,可以通过传递DependentCloneOption.BlockCommitUntilCompete值到DependentClone方法来创建依赖事务。通过这种方法,Commit方法的调用将会被阻塞,除非所有的依赖事务都已经完成。

代码
   
     
string connStr1 = " server=HEAIPING-PC;uid=sa;pwd=sa;database=DemoDB " ;
string connStr2 = " server=HEAIPING-PC;uid=sa;pwd=sa;database=DemoDB2 " ; // 另外一个数据库

string strSql1 = " delete from demoTb1 " ;
string strSql2 = " insert into DB2Tb values('222') " ;
protected void Page_Load( object sender, EventArgs e)
{
try
{
using (TransactionScope txScope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(connStr1))
{
conn.Open();
SqlCommand cmd
= new SqlCommand(strSql1, conn);
cmd.ExecuteNonQuery();
DependentTransaction depTx
= Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
ThreadPool.QueueUserWorkItem(AsyncProc, depTx);
txScope.Complete();
}
}
}
catch
{
}
}

private void AsyncProc( object state)
{
DependentTransaction depTx
= state as DependentTransaction;
try
{
using (SqlConnection conn = new SqlConnection(connStr2))
{
conn.Open();
conn.EnlistTransaction(depTx);
SqlCommand cmd
= new SqlCommand(strSql2, conn);
cmd.ExecuteNonQuery();
depTx.Complete();
}
}
catch
{
depTx.Rollback();

}
}

其实也没什么,主要是通过                    DependentTransaction depTx = Transaction.Current.DependentClone();来获取当前线程的事务然后传给另外一个线程,通过DependentCloneOption.BlockCommitUntilComplete属性来保证特定线程的Complete方法和整个事务的Commit方法的执行顺序。

以异步的方式完成事务

  可以通过异步的方式来管理事务的执行,为了等待事务完成而阻塞一个线程会对性能产生负面的影响,可以通过异步来完成。需要调用BeginCommit方法。该方法以一个委托作为参数,而在事务完成的时候会调用这个委托。在这个委托方法中。只需调用EndCommit方法即可。

代码
   
     
protected void Page_Load( object sender, EventArgs e)
{
string connStr1 = " server=HEAIPING-PC;uid=sa;pwd=sa;database=DemoDB " ;
string connStr2 = " server=HEAIPING-PC;uid=sa;pwd=sa;database=DemoDB2 " ; // 另外一个数据库

string strSql1 = " delete from demoTb1 " ;
string strSql2 = " insert into DB2Tb values('222') " ;
try
{
CommittableTransaction tx
= new CommittableTransaction();
// 对第一个数据库的操作
using (SqlConnection conn1 = new SqlConnection(connStr1))
{
conn1.Open();
// 注册事务
conn1.EnlistTransaction(tx);
SqlCommand cmd
= new SqlCommand(strSql1, conn1);
cmd.ExecuteNonQuery();
}
// 对第二个数据库的操作
using (SqlConnection conn2 = new SqlConnection(connStr2))
{
conn2.Open();
// 注册事务
conn2.EnlistTransaction(tx);
SqlCommand cmd
= new SqlCommand(strSql2, conn2);
cmd.ExecuteNonQuery();
}
tx.BeginCommit(OnCommited, tx);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}

private void OnCommited(System.IAsyncResult asyncResult)
{
CommittableTransaction tx
= asyncResult as CommittableTransaction;
try
{
using (tx)
{
tx.EndCommit(asyncResult);
}
}
catch
{
}
}

异步完成

你可能感兴趣的:(transaction)