即使未调用System.Transactions.TransactionScope.Commit(),也会提交数据

时间:2009-11-10 12:21:48

标签: c# .net transactions transactionscope

在什么情况下,包含在System.Transactions.TransactionScope中的代码仍然可以提交,即使抛出异常并且最外层的范围从未调用过提交?

using (var tx = new TransactionScope())中包含一个顶级方法,它以同样的方式调用同样使用TransactionScope的方法。

我正在使用带有关联tableadapters的类型化数据集。是不是因为某些原因,适配器中的命令没有出现?你们中的任何人都知道如何检查他们是否参加了环境的TransactionScope吗?

4 个答案:

答案 0 :(得分:8)

答案结果是因为我在<{strong> TransactionScope对象之后创建了SqlConnection对象

我离开了这个:

using (new ConnectionScope())
using (var transaction = new TransactionScope())
{
    // Do something that modifies data

    transaction.Complete();
}

到此:

using (var transaction = new TransactionScope())
using (new ConnectionScope())
{
    // Do something that modifies data

    transaction.Complete();
}

现在它有效!

故事的寓意是创建你的TransactionScope 第一个

答案 1 :(得分:2)

显而易见的情况是显式指定了新的(RequiresNew)/ null(Suppress)事务 - 但是还存在可能导致连接错过事务的超时/解除绑定故障。请参阅此earlier post(此修复只是一个连接字符串更改)或full details

答案 2 :(得分:0)

请注意TransactionScope的工作原理:
它在使用范围开始时设置属性System.Transactions.Transaction.Current,然后在使用范围结束时将其设置回先前的值。

以前的值取决于声明给定范围的位置。它可以在另一个范围内。

您可以修改如下代码:

using (var sqlConnection = new ConnectionScope())
using (var transaction = new TransactionScope())
{
    sqlConnection.EnlistTransaction(System.Transactions.Transaction.Current);
    // Do something that modifies data
    transaction.Complete();
}

我向那些代码更复杂并且不能简单地更改代码以首先打开数据库连接的人展示了这种可能性。

答案 3 :(得分:0)

此示例(C#,. NetFramework 4.7.1)说明了即使代码包装在TransactionScope中,我们也可以持久保存到数据库。第一个insert将被回滚,而第二个insert将被插入而没有事务。

See my related post,在这里我寻求帮助以检测到这一点。


using (var transactionScope = new TransactionScope())
{
    using (var connection = new SqlConnection("Server=localhost;Database=TestDB;Trusted_Connection=True"))
    {
        connection.Open();

        new SqlCommand($"INSERT INTO TestTable VALUES('This will be rolled back later')", connection).ExecuteNonQuery();

        var someNestedTransaction = connection.BeginTransaction();
        someNestedTransaction.Rollback();

        new SqlCommand($"INSERT INTO TestTable VALUES('This is not in a transaction, and will be committed')", connection).ExecuteNonQuery();
    }

    throw new Exception("Exiting.");

    transactionScope.Complete();
}