.net - 如何加入 TransactionScope?
问题描述
简洁版本
我如何加入正在进行的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 操作在一个事务中;并且可以回滚。
自动 BeginTransaction、提交和回滚
SqlClient库知道要检查:
- System.Transactions.Current
并在内部自动:
- 开始数据库事务
- 调用Scope.Complete时提交数据库事务
- 回滚作用域时回滚数据库事务
这一切都只是魔术。
- 不知何故
DbConnection
收到通知打电话.Commit
- 并以某种方式
DbConnection
收到通知呼叫.Rollback
我怎么做?
我有一堂课也有交易。而不是强迫调用者调用:
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);
实际的实现是简单的样板通知:
- Prepare:事务管理器要求您对事务是否可以提交进行投票:
- 投票Yes:
preparingEnlistment.Prepared();
- 投票No:
preparingEnlistment.ForceRollback();
- 投票Yes:
- 提交:做你的事情来提交并声明你已经完成了你的入伍:
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();
}
推荐阅读
- wget - 尝试从古腾堡项目 (wget) 下载所有书籍时连接被拒绝
- javascript - 在这种情况下是否有更好的 RXJs Operator 可以使用?
- neo4j - Neo4j errorMessages': {'无效输入 \'a\': 预期 \'u/U\'}
- javascript - 如何修改对象
- python - 如何显示/查看“sklearn.utils.Bunch”数据集?
- reactjs - 添加 react-beautiful-dnd 有警告;不工作
- c# - 从 FileSystemWatcher 创建一个子窗口
- javascript - Javascript标签位置
- c++ - 从 __FILE__ 编译时修剪路径和扩展名
- excel - VBA Excel:如何在组合的 Max、Index、Right 语句中使用命名范围