1

I've the following function that allows me to pass in a object and populate that object with the returning data, if any.

I've modified the function so that it can be called asynchronously.

public static async Task<MySqlDataReader> MySQLReturnReader(string sName, List<MySqlParameter> oParameters, Action<MySqlDataReader> fn)
{
    using (MySqlConnection oConn = new MySqlConnection(MasterConn))
    {
        await oConn.OpenAsync();

        using (MySqlCommand oMySqlCommand = new MySqlCommand(sName, oConn))
        {
           oMySqlCommand.CommandType = CommandType.StoredProcedure;

            if (oParameters != null)
            {
                foreach (MySqlParameter oPar in oParameters)
                {
                    oMySqlCommand.Parameters.Add(oPar);
                }
            }

            oMySqlCommand.Connection.Open();

            using (MySqlDataReader oReader = oMySqlCommand.ExecuteReaderAsync())
            {
               fn(oReader);
            }

        }
    }
    return;
}

My class object is something like;

public class MyClass
{
     public int Id {get;set;}
     public string Name {get;set;}
     ...
}

The function can be called like

 List<MyClass> oMyClassList = new List<MyClass>();
 List<MySqlParameter> oParams = new List<MySqlParameter>();

 List<int> Ids = new List<int>(500);
 Ids.Add(1);
 Ids.Add(2);
 ...
 Ids.Add(499);

 foreach(int Id in Ids)
 {
    MySQLReturnReader("SPCheck", oParams, oRes =>
        {
                while (oRes.Read())
                {
                   MyClass oMyClass = new MyClass();                      
                   oMyClass.Id = Convert.ToInt32(oRes["Id"]);                       
                   oMyClass.Name = oRes["Name"].ToString();
                }

                oMyClassList.Add(oMyClass);
        }
        );


 }

The problem is I'm getting the compilation error of 'Cannot implicitly convert type 'System.Threading.Tasks.Task' to 'MySql.Data.MySqlClient.MySqlDataReader'. Where am I going wrong ?

I'm wanting to use ExecuteReaderAsync in this way, as the Stored procedure called is very complex and would prefer to run the requests in parallel.

2 Answers 2

0

In your code, you have:

using (MySqlDataReader oReader = oMySqlCommand.ExecuteReaderAsync())

The compiler error Cannot implicitly convert type 'System.Threading.Tasks.Task' to 'MySql.Data.MySqlClient.MySqlDataReader' means that you need to use the await keyword to "unwrap" the task returned by ExecuteReaderAsync:

using (MySqlDataReader oReader = await oMySqlCommand.ExecuteReaderAsync())

Note however that if you're using the official MySql.Data package, this call won't actually execute asynchronously. The Async methods in the MySql.Data connector aren't asynchronous; they block on network I/O and only return when the DB operation is complete. (For a much more detailed discussion, see this question and its top answer.) MySQL bug #70111 reports this problem in the MySQL connector.

To get truly asynchronous DB operations, you'll have to wait until that bug is fixed, or switch to a different connector. I've been developing a new, fully async connector that should be a drop-in replacement for MySql.Data; to try it out, install MySqlConnector from NuGet; its source is at GitHub.

Sign up to request clarification or add additional context in comments.

Comments

-1

This most likely indicates that the library you're using doesn't support ExecuteReaderAsync(), so you're just calling the default implementation inherited from DbCommand. This is why it returns the general DbDataReader (instead of the MySQL-specific one). And this also means that your code won't actually be asynchronous, the default version of ExecuteReaderAsync() is just a synchronous wrapper around ExecuteReader().

So, I think you should directly use the old ExecuteReader(), until your library adds support for ExecuteReaderAsync().

4 Comments

I understand your answer, however is there a workaround so that my call will be asynchronous ?
@Tommo1977 I don't think you can, you simply can't make synchronous library into asynchronous without modifying the library. You can always use Task.Run() to execute the synchronous methods, but that's not really asynchronous (it still blocks a thread).
Thanks. How would I adapt my example to use Task.Run(). I know it wouldn't be really async, but it would allow multiple calls to the Stored procedure to be made at the same time.
MySql.Data has supported ExecuteReaderAsync for a long time (it just doesn't implement it properly; see my answer). The compiler error the OP posted simply means the code is lacking the await keyword.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.