views:

25

answers:

1

I am using SubSonic 2.1 and entcountered a problem while executing a Transaction with

SharedDbConnectionScope and TransactionScope. The problem is that in the obj.Save() method I get an "The connection must be valid and open" exception

I tracked down the problem to this line:

// Loads a SubSonic ActiveRecord object
User user = new User(User.Columns.Username, "John Doe");

in this Constructor of the User class a method "LoadParam" is called which eventually does

if (rdr != null)
    rdr.Close();

It looks like the rdr.Close() implicitly closes my connection which is fine when using the AutomaticConnection. But during a transaction it is usally not a good idea to close the connection :-)

My Question is if this is by design or if it's an error in the MySqlDataReader.

A: 

That was tricky! After a bit debugging I found the following method in the SubSonic2 MySqlDataReader.cs file:

    public override IDataReader GetReader(QueryCommand qry)
    {
        AutomaticConnectionScope conn = new AutomaticConnectionScope(this);

        ...

        cmd.Connection = (MySqlConnection)conn.Connection;

        IDataReader rdr;

        try
        {
            rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
        }
        catch(MySqlException x)
        {
            conn.Dispose();
            throw x;
        }

        ...
    }

Which is wrong since I am using a SharedDbConnection. In the SqlDataProvider it has been fixed already but not for MySqlDataReader.

It should look like this:

        try
        {
            // if it is a shared connection, we shouldn't be telling the reader to close it when it is done
            rdr = conn .IsUsingSharedConnection ?
                      cmd.ExecuteReader() : 
                      cmd.ExecuteReader(CommandBehavior.CloseConnection);
        }
        catch (MySqlException)
        {
            // AutoConnectionScope will figure out what to do with the connection
            conn.Dispose();
            //rethrow retaining stack trace.
            throw;
        }

Pretty heavy bug, it rendered Querying in a Transaction impossible (I must admit I never needed this before).

SchlaWiener