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

时间:2011-11-21 19:29:47

标签: c# .net sql transactionscope

目标很简单 - 通过单元测试插入回滚数据。这是怎么回事。在单元测试中,调用一个方法来创建新连接并插入一些数据。之后,单元测试会创建一个新连接,并尝试查找插入的内容并断言。我希望用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,但我收到此错误。 enter image description here

4 个答案:

答案 0 :(得分:1)

我不认为你错过了这一点,只是错误地攻击了这个问题。

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

答案 1 :(得分:1)

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

I'd recommend looking at this article,它显示了使用MSDTC回滚单元测试时需要完成的所有各个步骤。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

作为参考,以下控制台应用程序正确输出3 rows,并且不会将行提交到数据库(使用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();
        }
    }
}