Search code examples
mysqlsubsonicmysqldatareader

SubSonic: MySqlDataReader closes connection


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.


Solution

  • 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).