如何加入 TransactionScope?
How to enlist with a TransactionScope?
精简版
我如何加入正在进行的 TransactionScope?
长版
如果您使用 TransactionScope,您可以创建一个 "ambient" 事务:
using (TransactionScope scope = new TransactionScope())
{
//...stuff happens, then you complete...
// The Complete method commits the transaction.
scope.Complete();
}
那有什么用?好吧,.NET 框架中有一些 classes 知道如何通过检查 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库知道要检查:
- System.Transactions.Current
并在内部自动:
- 开始数据库事务
- 调用Scope.Complete
时提交数据库事务
- 回滚作用域时回滚数据库事务
这一切都是魔法。
DbConnection
以某种方式收到呼叫 .Commit
的通知
- 并且
DbConnection
以某种方式收到调用 .Rollback
的通知
我该怎么做?
我有一个 class 也有交易。而不是强制调用者调用:
using (IContosoTransaction tx = turboEncabulator.BeginTransaction())
{
try
{
turboEncabulator.UpendCardinalGrammeters();
}
catch (Exception ex)
{
tx.Rollback();
throw;
}
tx.Commit();
}
如果他们能直接打电话就好了:
turboEncabulator.UpendCardinalGrammeters();
我的代码将简单地检查:
- System.Transactions.Current
如果有交易正在进行,我会:
- 开始交易
- 等待通知提交
- 或者等待通知回滚
但是我该怎么做呢?
我如何在正在进行的 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);
然后需要实现IEnlistmentNotification
的四个通知方法:
void Prepare(PreparingEnlistment preparingEnlistment);
void Commit(Enlistment enlistment);
void InDoubt(Enlistment enlistment);
void Rollback(Enlistment enlistment);
实际实现是简单的样板通知:
- 准备:事务管理器正在征求您对事务是否适合提交的投票:
- 投票是:
preparingEnlistment.Prepared();
- 投票否:
preparingEnlistment.ForceRollback();
- 提交:尽你所能提交并声明你已完成入伍:
enlistment.Done();
- InDoubt:通知事务管理器与事务中涉及的其他人失去联系。通过让他们知道您已完成入伍来回应:
enlistment.Done();
- Rollback:事务正在回滚的通知。做任何类型的回滚工作,让他们知道你已经完成了入伍:
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();
}
精简版
我如何加入正在进行的 TransactionScope?
长版
如果您使用 TransactionScope,您可以创建一个 "ambient" 事务:
using (TransactionScope scope = new TransactionScope())
{
//...stuff happens, then you complete...
// The Complete method commits the transaction.
scope.Complete();
}
那有什么用?好吧,.NET 框架中有一些 classes 知道如何通过检查 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库知道要检查:
- System.Transactions.Current
并在内部自动:
- 开始数据库事务
- 调用Scope.Complete 时提交数据库事务
- 回滚作用域时回滚数据库事务
这一切都是魔法。
DbConnection
以某种方式收到呼叫.Commit
的通知
- 并且
DbConnection
以某种方式收到调用.Rollback
的通知
我该怎么做?
我有一个 class 也有交易。而不是强制调用者调用:
using (IContosoTransaction tx = turboEncabulator.BeginTransaction())
{
try
{
turboEncabulator.UpendCardinalGrammeters();
}
catch (Exception ex)
{
tx.Rollback();
throw;
}
tx.Commit();
}
如果他们能直接打电话就好了:
turboEncabulator.UpendCardinalGrammeters();
我的代码将简单地检查:
- System.Transactions.Current
如果有交易正在进行,我会:
- 开始交易
- 等待通知提交
- 或者等待通知回滚
但是我该怎么做呢?
我如何在正在进行的 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);
然后需要实现
IEnlistmentNotification
的四个通知方法:void Prepare(PreparingEnlistment preparingEnlistment);
void Commit(Enlistment enlistment);
void InDoubt(Enlistment enlistment);
void Rollback(Enlistment enlistment);
实际实现是简单的样板通知:
- 准备:事务管理器正在征求您对事务是否适合提交的投票:
- 投票是:
preparingEnlistment.Prepared();
- 投票否:
preparingEnlistment.ForceRollback();
- 投票是:
- 提交:尽你所能提交并声明你已完成入伍:
enlistment.Done();
- InDoubt:通知事务管理器与事务中涉及的其他人失去联系。通过让他们知道您已完成入伍来回应:
enlistment.Done();
- Rollback:事务正在回滚的通知。做任何类型的回滚工作,让他们知道你已经完成了入伍:
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();
}