Search code examples
c#mysqltransactionscope

TransactionScope yields System.Transactions.TransactionException


I have a database class with methods as shown below. Both foo and bar are all-or-nothing operations. Hence the need for transactions. Note that I'm using MySQL 5.5.21 together with MySQL .NET Connector 6.6.4.

public void foo()
{
    using (var transaction = new TransactionScope())
    {
        // This call yields a 'System.Transactions.TransactionException'
        bar();

        insertStuff();

        transaction.Complete();
    }
}

public void bar()
{
    using (var transaction = new TransactionScope())
    {
        insertStuff();
        insertStuff();

        transaction.Complete();
    }
}

private void insertStuff()
{
    using (var connection = CreateConnection()) // Using the same connection string!
    {
        connection.ConnectionString = ConnectionString;
        connection.Open();
    }
}

I did try specifying TransactionScopeOption.RequiresNew in the constructor, but it didn't help. I also tried explicitly open a connection before each transaction scope, but still no success.

What I want is this:

  • If I call bar alone, there should be one transaction.
  • If I call foo (which in turn calls bar), there should be one transaction.

Q: Am I facing a limitation of MySQL .NET Connector or am I doing something wrong?

EDIT: The exact error is this: The operation is not valid for the state of the transaction. So, as soon as I call Open() on the connection the transaction bails out...


Solution

  • Use bar as shown:

    public void bar()
    {
            insertStuff();
            insertStuff();
    }
    

    Is it work?

    For best practice you can create transaction using IDbConnection.BeginTransaction() because the transaction is connection scoped.

    public void foo()
    {
        using(IDbConnection connection = new MySqlConnection(/*connection string*/))
        {
            connection.Open();
            using(IDbTransction transaction = connection.BeginTransaction())
            {
                bar(connection);
                insertStuff(connection);
    
                transaction.Commit();
            }
    
        }
    }
    
    public void bar(IDbConnection connection)
    {
            insertStuff(connection);
            insertStuff(connection);
    }
    
    private void insertStuff(IDbConnection connection)
    {
         // do stuff
    }