我如何加入正在进行的TransactionScope?
如果您使用TransactionScope,您可以创建“环境”交易:
using (TransactionScope scope = new TransactionScope())
{
//...stuff happens, then you complete...
// The Complete method commits the transaction.
scope.Complete();
}
那有什么用呢?嗯,.NET 框架中有一些类知道如何通过检查
static
: 来检查是否存在环境正在进行的事务
这让他们知道有一笔交易正在进行中。
例如,如果您有一些任意数据库操作,否则不考虑事务:
void DropStudents()
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "DROP TABLE Students;";
cmd.ExecuteNonQuery();
}
}
如果你把它放在 TransactionScope 的中间:
using (TransactionScope scope = new TransactionScope())
{
DropStudents();
// The Complete method commits the transaction.
scope.Complete();
}
突然间您的 ADO.net 操作处于事务中;并且可以回滚。
SqlClient库知道要检查:
并自动在内部:
这一切都只是魔法。
DbConnection
收到了致电.Commit
DbConnection
收到了呼叫.Rollback
我有一堂课也有交易。而不是强迫呼叫者打电话:
using (IContosoTransaction tx = turboEncabulator.BeginTransaction())
{
try
{
turboEncabulator.UpendCardinalGrammeters();
}
catch (Exception ex)
{
tx.Rollback();
throw;
}
tx.Commit();
}
如果他们能打电话就好了:
turboEncabulator.UpendCardinalGrammeters();
我的代码将简单地检查:
如果有交易正在进行,我会:
但是我该怎么做呢?
我如何向正在进行的 TransactionScope 注册自己以获取这些通知?
其实没那么糟糕。
通过查看是否分配了
System.Transactions.Transaction.Current
来检查是否有正在进行的事务。如果有,交易中Enlist
:
//Enlist in any current transactionScope if one is active
if (System.Transactions.Transaction.Current != null)
System.Transactions.Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None);
我传递
this
作为将通过其必须实现的 IEnlistmentNotification
接口获取通知回调的对象。
IEnlistmentNotification
的四种通知方法:
void Prepare(PreparingEnlistment preparingEnlistment);
void Commit(Enlistment enlistment);
void InDoubt(Enlistment enlistment);
void Rollback(Enlistment enlistment);
实际的实现是简单的样板通知:
preparingEnlistment.Prepared();
preparingEnlistment.ForceRollback();
enlistment.Done();
enlistment.Done();
enlistment.Done();
public void Prepare(PreparingEnlistment preparingEnlistment)
{
//The transaction manager is asking for our vote if the transaction
//can be committed
//Vote "yes" by calling .Prepared:
preparingenlistment.Prepared();
//Vote "no" by calling .ForceRollback:
//preparingEnlistment.ForceRollback();
}
public void Commit(Enlistment enlistment)
{
//The transaction is being committed - do whatever it is we do to commit.
//Let them know we're done with the enlistment.
enlistment.Done();
}
public void InDoubt(Enlistment enlistment)
{
//Do any work necessary when indoubt notification is received.
//This method is called if the transaction manager loses contact with one or more participants,
//so their status is unknown.
//If this occurs, you should log this fact so that you can investigate later whether any of the
//transaction participants has been left in an inconsistent state.
//Let them know we're done with the enlistment.
enlistment.Done();
}
public void Rollback(Enlistment enlistment)
{
//If any resource manager reported a failure to prepare in phase 1, the transaction manager invokes
//the Rollback method for each resource manager and indicates to the application the failure of the commit.
//Let them know we're done with the enlistment.
enlistment.Done();
}