C# TransactionScope 如何回滚事务?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/494550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does TransactionScope roll back transactions?
提问by mezoid
I'm writing an integration test where I will be inserting a number of objects into a database and then checking to make sure whether my method retrieves those objects.
我正在编写一个集成测试,我将在其中插入许多对象到数据库中,然后检查以确保我的方法是否检索到这些对象。
My connection to the database is through NHibernate...and my usual method of creating such a test would be to do the following:
我与数据库的连接是通过 NHibernate 进行的……而我创建此类测试的常用方法是执行以下操作:
NHibernateSession.BeginTransaction();
//use nhibernate to insert objects into database
//retrieve objects via my method
//verify actual objects returned are the same as those inserted
NHibernateSession.RollbackTransaction();
However, I've recently found out about TransactionScopewhich apparently can be used for this very purpose...
但是,我最近发现了TransactionScope显然可以用于此目的......
Some example code I've foundis as follows:
public static int AddDepartmentWithEmployees(Department dept)
{
int res = 0;
DepartmentAdapter deptAdapter = new DepartmentAdapter();
EmployeeAdapter empAdapter = new EmployeeAdapter();
using (TransactionScope txScope = new TransactionScope())
{
res += deptAdapter.Insert(dept.DepartmentName);
//Custom method made to return Department ID
//after inserting the department "Identity Column"
dept.DepartmentID = deptAdapter.GetInsertReturnValue();
foreach(Employee emp in dept.Employees)
{
emp.EmployeeDeptID = dept.DepartmentID;
res += empAdapter.Insert(emp.EmployeeName, emp.EmployeeDeptID);
}
txScope.Complete();
}
return res;
}
I believe that if I don't include the line txScope.Complete()
that the data inserted will be rolled back. But unfortunately I don't understand how that is possible... how does the txScope
object keep a track of the deptAdapter
and empAdapter
objects and their transactions on the database.
我相信如果我不包括txScope.Complete()
插入的数据将被回滚的行。但不幸的是,我不明白这怎么可能……txScope
对象如何跟踪数据库上的deptAdapter
和empAdapter
对象及其事务。
I feel like I'm missing a bit of information here...am I really able to replace my BeginTransaction()
and RollbackTransaction(
) calls by surrounding my code using TransactionScope
?
我觉得我在这里遗漏了一些信息......我真的能够通过使用我的代码来替换我的BeginTransaction()
和RollbackTransaction(
) 调用TransactionScope
吗?
If not, how then does TransactionScope
work to roll back transactions?
如果没有,那么如何TransactionScope
回滚事务?
采纳答案by JoshBerke
Essentially TransactionScope doesn't track your Adapter's, what it does is it tracks database connections. When you open a DB connection the connections will looks if there is an ambient transaction (Transaction Scope) and if so enlist with it. Caution if there are more the one connection to the same SQL server this will escalate to a Distribtued Transaction.
本质上 TransactionScope 不会跟踪您的适配器,它所做的是跟踪数据库连接。当您打开数据库连接时,连接将查看是否存在环境事务(事务范围),如果有,则使用它。注意,如果有多个连接到同一 SQL 服务器,这将升级为分布式事务。
What happens since you're using a using block you are ensuring dispose will be called even if an exception occurs. So if dispose is called before txScope.Complete() the TransactionScope will tell the connections to rollback their transactions (or the DTC).
自从您使用 using 块以来会发生什么,您确保即使发生异常也会调用 dispose 。因此,如果在 txScope.Complete() 之前调用 dispose,则 TransactionScope 将告诉连接回滚其事务(或 DTC)。
回答by casperOne
The TransactionScope
classworks with the Transaction
class, which is thread-specific.
该TransactionScope
班的工作原理与Transaction
阶级,这是线程特定的。
When the TransactionScope
is created, it checks to see if there is a Transaction
for the thread; if one exists then it uses that, otherwise, it creates a new one and pushes it onto the stack.
当TransactionScope
被创建,它会检查是否有Transaction
该线程; 如果存在,则使用它,否则,它会创建一个新的并将其压入堆栈。
If it uses an existing one, then it just increments a counter for releases (since you have to call Dispose
on it). On the last release, if the Transaction
was not comitted, it rolls back all the work.
如果它使用现有的,那么它只会增加一个发布的计数器(因为你必须调用Dispose
它)。在上一个版本中,如果Transaction
未提交,它会回滚所有工作。
As for why classes seem to magically know about transactions, that is left as an implementation detail for those classes that wish to work with this model.
至于为什么类似乎神奇地知道事务,这留给那些希望使用此模型的类的实现细节。
When you create your deptAdapter
and emptAdapter
instances, they check to see if there is a current transaction on the thread (the static Current
propertyon the Transaction
class). If there is, then it registers itself with the Transaction
, to take part in the commit/rollback sequence (which Transaction
controls, and might propogate to varying transaction coordinators, such as kernel, distributed, etc.).
当您创建deptAdapter
和emptAdapter
实例时,它们会检查线程上是否存在当前事务(类上的静态Current
属性Transaction
)。如果有,则它向Transaction
,注册自己以参与提交/回滚序列(该序列Transaction
控制并可能传播到不同的事务协调器,例如内核、分布式等)。