TransactionScope如何回滚事务?

发布于 2024-07-13 03:08:28 字数 1852 浏览 7 评论 0原文

我正在编写一个集成测试,我将在数据库中插入许多对象,然后检查以确保我的方法是否检索到这些对象。

我与数据库的连接是通过 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();

但是,我最近发现了 TransactionScope 显然可以用于此目的......

一些我找到的示例代码如下:

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;

}

我相信,如果我不包含行 txScope.Complete()< /code> 插入的数据将被回滚。 但不幸的是,我不明白这是怎么可能的...txScope 对象如何跟踪 deptAdapterempAdapter 对象以及他们在数据库上的交易。

我觉得我在这里丢失了一些信息...我真的能够通过使用 < 包围我的代码来替换我的 BeginTransaction()RollbackTransaction() 调用吗代码>事务范围?

如果不是,那么 TransactionScope 如何回滚事务?

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:

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 TransactionScope which apparently can be used for this very purpose...

Some example code I've found is 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.

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?

If not, how then does TransactionScope work to roll back transactions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烙印 2024-07-20 03:08:28

本质上,TransactionScope 并不跟踪您的适配器,它所做的是跟踪数据库连接。 当您打开数据库连接时,连接将查看是否存在环境事务(事务范围),如果有,则加入它。 注意,如果有多个连接到同一 SQL 服务器,这将升级为分布式事务。

由于您使用的是 using 块,因此即使发生异常,您也会确保调用 dispose 会发生什么。 因此,如果在 txScope.Complete() 之前调用 dispose,TransactionScope 将告诉连接回滚其事务(或 DTC)。

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.

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).

苦妄 2024-07-20 03:08:28

TransactionScope 有效使用 Transaction ,这是特定于线程的。

当创建 TransactionScope 时,它会检查线程是否有 Transaction; 如果存在,则使用它,否则,它创建一个新的并将其推入堆栈。

如果它使用现有的版本,那么它只会增加版本计数器(因为您必须调用 丢弃)。 在上一个版本中,如果 Transaction 未提交,则会回滚所有工作。

至于为什么类似乎神奇地了解事务,这将作为那些希望使用此模型的类的实现细节。

当您创建 deptAdapteremptAdapter 实例时,它们会检查线程上是否存在当前事务(静态 Transaction 类上的Current 属性 )。 如果存在,那么它会向 Transaction 注册自己,以参与提交/回滚序列(由 Transaction 控制,并且可能传播到不同的事务协调器,例如内核、分布式等)。

The TransactionScope class works with the Transaction class, which is thread-specific.

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.

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.

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 property on 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.).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文