pritaeas 2,194 ¯\_(ツ)_/¯ Moderator Featured Poster

I've posted a bug report here:

http://tracker.firebirdsql.org/browse/DNET-540

If someone using Firebird and C# could verify this for me, or shed some light on (other) possible issues, that would be much appreciated. The code works as expected with 2.5.1, but does not with 2.5.2. Note: the sample is built on .NET 3.5

The connection string contains Enlist=True.

The code is the following (a little different than the one posted in the bug report, but it acts the same):

public partial class frmMain : Form
{
    private TransactionScopeOption transactionScopeOption;
    private TransactionOptions transactionOptions;

    public frmMain()
    {
        InitializeComponent();

        transactionScopeOption = TransactionScopeOption.Required;
        transactionOptions = new TransactionOptions()
            {
                IsolationLevel = IsolationLevel.ReadUncommitted,
                Timeout = TimeSpan.FromMinutes(2)
            };
    }

    private void btnTestFb_Click(object sender, System.EventArgs e)
    {
        try
        {
            using (TransactionScope scope = new TransactionScope(transactionScopeOption, transactionOptions))
            {
                using (FbConnection connection = new FbConnection(
                    ConfigurationManager.ConnectionStrings["ConnectionStringFb"].ConnectionString))
                {
                    connection.Open();

                    NestedInserts(connection);

                    scope.Complete();

                    // Additional question: Is this needed?
                    // connection.Close(); 
                }
            }

            MessageBox.Show("Done.");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void ExecuteNonQuery(FbConnection connection, string commandText)
    {
        using (FbCommand command = new FbCommand(commandText, connection))
        {
            command.ExecuteNonQuery();
        }
    }

    private void NestedInserts(FbConnection connection)
    {
        using (TransactionScope scope = new TransactionScope(transactionScopeOption, transactionOptions))
        {
            InsertA(connection);

            scope.Complete();
        }
    }

    private void InsertA(FbConnection connection)
    {
        using (TransactionScope scope = new TransactionScope(transactionScopeOption, transactionOptions))
        {
            ExecuteNonQuery(connection, "INSERT INTO TABLE_A (DESCRIPTION) VALUES ('A')");

            InsertB(connection);

            scope.Complete();
        }
    }

    private void InsertB(FbConnection connection)
    {
        using (TransactionScope scope = new TransactionScope(transactionScopeOption, transactionOptions))
        {
            ExecuteNonQuery(connection, "INSERT INTO TABLE_B (DESCRIPTION) VALUES ('B')");

            InsertC(connection);

            scope.Complete();
        }
    }

    private void InsertC(FbConnection connection)
    {
        using (TransactionScope scope = new TransactionScope(transactionScopeOption, transactionOptions))
        {
            ExecuteNonQuery(connection, "INSERT INTO TABLE_C (DESCRIPTION) VALUES ('C')");

            InsertD(connection);

            scope.Complete();
        }
    }

    private void InsertD(FbConnection connection)
    {
        using (TransactionScope scope = new TransactionScope(transactionScopeOption, transactionOptions))
        {
            // intentionally trigger an exception to abort the transaction
            ExecuteNonQuery(connection, "INSERT INTO TABLE_D");

            scope.Complete();
        }
    }
}