是否可以使用 TransactionScope 回滚已提交的数据?

发布于 2024-12-17 02:24:46 字数 978 浏览 0 评论 0原文

目标很简单 - 回滚单元测试插入的数据。事情是这样的。在单元测试中,调用一个方法来创建新连接并插入一些数据。之后,单元测试创​​建一个新连接并尝试查找已插入的内容并对其进行断言。我希望用 TransactionScope 包装这两件事,而不是调用 Complete 并看到插入的数据回滚。那并没有发生。我做错了什么还是我只是没有抓住要点?

using (new TransactionScope())
{
    // call a method that inserts data
    var target = new ....
    target.DoStuffAndEndupWithDataInDb();

    // Now assert what has been added.
    using (var conn = new SqlConnection(connectionString))
    using (var cmd = conn.CreateCommand())
    {
        // Just read the data from DB
        cmd.CommandText = "SELECT...";
        conn.Open();
        int count = 0;
        using (var rdr = cmd.ExecuteReader())
        {
            // Read records here
            ...
            count++;
        }

        // Expecting, say, 3 records here
        Assert.AreEqual(3, count);
    }
}

编辑:我认为我的机器上没有运行和配置 DTC。因此,我启动了该服务并尝试配置 DTC,但收到此错误。 在此处输入图像描述

The goal is simple - rollback data inserted by a unit test. Here is how it goes. In a unit test, a method is called that creates a new connection and inserts some data. After that a unit test creates a new connection and tries to find what has been inserted and assert that. I was hoping to wrap these two things with TransactionScope, not call Complete and see inserted data rolled back. That's not happening. Am I doing something wrong or I am just missing the point?

using (new TransactionScope())
{
    // call a method that inserts data
    var target = new ....
    target.DoStuffAndEndupWithDataInDb();

    // Now assert what has been added.
    using (var conn = new SqlConnection(connectionString))
    using (var cmd = conn.CreateCommand())
    {
        // Just read the data from DB
        cmd.CommandText = "SELECT...";
        conn.Open();
        int count = 0;
        using (var rdr = cmd.ExecuteReader())
        {
            // Read records here
            ...
            count++;
        }

        // Expecting, say, 3 records here
        Assert.AreEqual(3, count);
    }
}

EDIT: I don't think I had DTC running and configured on my machine. So I started the service and tried to configure DTC but I am getting this error.
enter image description here

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

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

发布评论

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

评论(4

遗忘曾经 2024-12-24 02:24:46

你在使用 MSTest 吗?那么你可以使用 MsTestExtensions
您的单元测试需要从 MSTestExtensionsTestFixture 派生,并且您的测试需要具有 TestTransaction 属性,它使用 AOP 自动启动事务并回滚。

are you using MSTest ? then you can use MsTestExtensions
you unit test needs to derive from MSTestExtensionsTestFixture and your test needs to have TestTransaction Attribute, it uses AOP to automatically start a transaction and roll it back.

唱一曲作罢 2024-12-24 02:24:46

我不认为你没有抓住重点,只是错误地解决了问题。

在 NUnit 术语中,概念是 [SetUp][TearDown] 方法。您已经在描述中定义了设置方法,并且您的拆卸方法应该撤消设置方法所做的操作(假设您的单元测试没有残留副作用)。

I don't think you're missing the point but just attacking the problem incorrectly.

In NUnit terms, the concepts are [SetUp] and [TearDown] methods. You've already defined the setup method in your description and your tear down method should just undo what the setup method did (assuming what you're unit testing has no residual side effects).

十秒萌定你 2024-12-24 02:24:46

您是否正确配置了分布式事务协调器?当尝试像这样使用 TransactionScope 时,这是一个很大的问题...如果未配置它,有时您会收到错误,但其他时候事务只会提交而不回滚。

我建议您查看这篇文章,它向您展示了所有内容使用 MSDTC 回滚单元测试所需执行的各个步骤。

Do you have Distributed Transaction Coordinator properly configured? This is a big gotcha when trying to use TransactionScope like this... if it isn't configured, sometimes you'll get an error, but other times the transaction will just commit and not rollback.

I'd recommend looking at this article, which shows you all the various steps that need to be done in order to rollback your unit tests using MSDTC.

聽兲甴掵 2024-12-24 02:24:46

您的代码应该按您的预期工作。如何在 DoStuffAndEndupWithDataInDb() 中添加数据?我想知道数据初始化是否不参与事务。

作为参考,以下控制台应用程序正确输出 3 行,并且不会将这些行提交到数据库(使用 SSMS 检查)。

public class Program
{
    private static void Main(string[] args)
    {
        using (var trx = new TransactionScope())
        {
            InitializeData();

            using (var connection = new SqlConnection("server=localhost;database=Test;integrated security=true"))
            using (var command = connection.CreateCommand())
            {
                command.CommandText = "select count(*) from MyTable";
                connection.Open();
                Console.WriteLine("{0} rows", command.ExecuteScalar());
            }
        }
        Console.ReadLine();
    }

    private static void InitializeData()
    {
        using (var connection = new SqlConnection("server=localhost;database=Test;integrated security=true"))
        using (var command = connection.CreateCommand())
        {
            command.CommandText = "insert into MyTable values (1),(2),(3)";
            connection.Open();
            command.ExecuteNonQuery();
        }
    }
}

Your code should work as you expect. How are you adding data in DoStuffAndEndupWithDataInDb()? I'm wondering whether the data initialization is not participating in the transaction.

For reference, the following console application correctly outputs 3 rows, and does not commit the rows to the database (checked using SSMS).

public class Program
{
    private static void Main(string[] args)
    {
        using (var trx = new TransactionScope())
        {
            InitializeData();

            using (var connection = new SqlConnection("server=localhost;database=Test;integrated security=true"))
            using (var command = connection.CreateCommand())
            {
                command.CommandText = "select count(*) from MyTable";
                connection.Open();
                Console.WriteLine("{0} rows", command.ExecuteScalar());
            }
        }
        Console.ReadLine();
    }

    private static void InitializeData()
    {
        using (var connection = new SqlConnection("server=localhost;database=Test;integrated security=true"))
        using (var command = connection.CreateCommand())
        {
            command.CommandText = "insert into MyTable values (1),(2),(3)";
            connection.Open();
            command.ExecuteNonQuery();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文