English 中文(简体)
Data committed even though System.Transactions.TransactionScope.Commit() not called
原标题:

Under what circumstances can code wrapped in a System.Transactions.TransactionScope still commit, even though an exception was thrown and the outermost scope never had commit called?

There is a top-level method wrapped in using (var tx = new TransactionScope()), and that calls methods that also use TransactionScope in the same way.

I m using typed datasets with associated tableadapters. Could it be that the commands in the adapter aren t enlisting for some reason? Do any of you know how one might check whether they are enlisting in the ambient TransactionScope or not?

最佳回答

The answer turned out to be because I was creating the TransactionScope object after the SqlConnection object.

I moved from this:

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

    transaction.Complete();
}

to this:

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

    transaction.Complete();
}

and now it works!

So the moral of the story is to create your TransactionScope first.

问题回答

The obvious scenario would be where a new (RequiresNew) / null (Suppress) transaction is explicitly specified - but there is also a timeout/unbinding glitch that can cause connections to miss the transaction. See this earlier post (the fix is just a connection-string change), or full details.

Be aware how TransactionScope works:
It sets property System.Transactions.Transaction.Current at the begining of using scope and then set it back to previous value at end of using scope.

Previous value depends on where given scope is declared. It can be inside another scope.


You can modify code like this:

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

I show this possibility for those who have their code more complicated and cannot simply change code to open DB connection first.

This example (C#, .NetFramework 4.7.1) shows how we can persist to the database even if the code is wrapped in a TransactionScope. The first insert will be rolled back, and the second insert will be inserted without transaction.

See my related post, where I ask for help in how to detect this.


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();
}





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签