Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Updating my project to Connector 2.3.x break my MySqlDataReader's results in some strange case. #1401

Answered by RioMcBoo
RioMcBoo asked this question in Q&A
Discussion options

IT WAS

public SQLResult Query(PreparedStatement stmt)
{
    try
    {
        var connection = new MySqlConnection(_connectionInfo.ConnectionString); 
        connection.Open();

        using MySqlCommand cmd = connection.CreateCommand();

        cmd.CommandText = stmt.CommandText;
        foreach (var parameter in stmt.Parameters)
            cmd.Parameters.AddWithValue("@" + parameter.Key, parameter.Value);

        return new SQLResult(cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection));
    }
    catch (MySqlException ex)
    {
        HandleMySQLException(ex, stmt.CommandText, stmt.Parameters);
        return new SQLResult();
    }
}
--------------------------
public class SQLResult
{
    MySqlDataReader _reader;

    public SQLResult() { }

    public SQLResult(MySqlDataReader reader)
    {
        _reader = reader;
        NextRow();
    }

    ~SQLResult()
    {
        _reader = null;
    }   

    public bool NextRow()
    {
        if (_reader == null)
            return false;

        if (_reader.Read())
            return true;

        _reader.Close();
        return false;
    }
}

IT BECAME

public class SQLResult : IDisposable
{
    MySqlDataReader _reader;

    public SQLResult() { }

    public SQLResult(MySqlDataReader reader)
    {
        _reader = reader;
        if (!NextRow())
        {
            Dispose();
        }
    }

    public bool NextRow()
    {
        return _reader.Read();
    }

    public void Dispose()
    {
        if (_reader != null)
        {
            _reader.Close();
            _reader = null;
        }
    }
}
You must be logged in to vote

https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling

The problem was about pool doesn't create a new reader after 2.3.х because it doesn't close current connection since now. (And it seems that now, being empty, the Reader itself closes and, together with the connection, passes into other hands without warning.)

And the stupid idea (maybe not) was using reader.Read() at creation reader's wrapper without any processing callback's bool value.

So I added in reader's wrapper the varification of this boolean value, and made it close the reader, and made link of it to be equal null.

Replies: 3 comments · 4 replies

Comment options

Might possibly be caused by #1277?

You haven't shown any relevant code AFAICT. How is MySqlBase<T>.Query implemented? Are you caching MySqlDataReader objects after disposing them?

You must be logged in to vote
1 reply
@RioMcBoo
Comment options

It seems to me that the problem may have been caused by this update, but it is definitely not due to something wrong in the code - otherwise I would have received an ObjectDisposedException

Comment options

You must be logged in to vote
2 replies
@bgrainger
Comment options

    ~SQLResult()
    {
        _reader = null;
    }

This code snippet is an enormous red flag. It has almost never been necessary to write a finalizer since .NET Framework 2.0 (almost 20 years ago); see https://joeduffyblog.com/2005/12/27/never-write-a-finalizer-again-well-almost-never/. It's also completely unnecessary to set a field (_result) to null because that will simply happen implicitly when the object is garbage-collected (which, ironically, is delayed by the presence of a finalizer).

The checks against if (_reader == null) when that can never be true (if the snippet you pasted is the entire class implementation) are another red flag.

The problem is almost certainly caused by misuse of the MySqlConnector API in your code. v2.2.7 must have permitted it, but v2.3.1 is "stricter" (in some sense) by requiring correct API use in order to return correct data. (In order to facilitate extremely high-performance code, MySqlConnector does not include explicit checks for all kinds of API misuse, so the outcome may be incorrect data rather than an exception.)

How is _connectionInfo.GetConnection(); implemented? Is that handing out (and reusing) the same connection? If so, that's probably the problem. If it's creating a new MySqlConnection, then you're leaking MySqlConnection objects, which is a different bug.

@RioMcBoo
Comment options

Thank you, I changed it, but it doesnt help it

Comment options

What does the SetQuery method do? How is _LoadMail called with its two SQLResult objects? Is SQLResult IDisposable? Who cleans up the MySqlDataReader that SQLResult has when it's done?

You must be logged in to vote
1 reply
@RioMcBoo
Comment options

https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling

The problem was about pool doesn't create a new reader after 2.3.х because it doesn't close current connection since now. (And it seems that now, being empty, the Reader itself closes and, together with the connection, passes into other hands without warning.)

And the stupid idea (maybe not) was using reader.Read() at creation reader's wrapper without any processing callback's bool value.

So I added in reader's wrapper the varification of this boolean value, and made it close the reader, and made link of it to be equal null.

Answer selected by RioMcBoo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.