Runs a MySQL query, returns Dictionary or false; I've been practicing C# and ASP.NET, and have been working on a somewhat larger-scale project than I am currently used to. I am sure there are horrible things wrong with this code that I will find out later, and would rather get some input on it now. 

One of the things I'm concerned with is the fact that RunSelectCommand can return false if the database fails to connect, or if the query returns nothing. 

Currently, in order to check for that, I do if (!(data is bool)) and if it's not I assume there is data to work with, and I return an error from the web server if not. 

If any more information is needed, please let me know! I am very excited for some real peer-reviewed code.

public object RunSelectCommand(MySqlCommand command, List&lt;MySqlParameter&gt; parameterCollection = null)
{
    using (MySqlConnection conn = new MySqlConnection(connectionString))
    using (var cmd = conn.CreateCommand())
    {
        try
        {
            conn.Open();
        }
        catch (MySqlException ex)
        {
            return ex;
        }
        cmd.CommandText = command.CommandText;
        if (parameterCollection != null) // if parameters for query are specified, add them here.
        {
            cmd.Parameters.AddRange(parameterCollection.ToArray());
        }
        using (var reader = cmd.ExecuteReader())
        {
            if (reader.Read())
            {
                Dictionary&lt;string, string&gt; data = new Dictionary&lt;string, string&gt;(); // This is designed for returning only 1 row at a time
                for (int i = 0; i &lt; (reader.FieldCount - 1); i++) // TODO seperate SelectAll command
                {
                    data.Add(reader.GetName(i), reader[i].ToString()); // Iterates through reader and adds data to Dictionary for output to JSON
                }
                conn.Close();
                return data;
            }
            else
            {
                conn.Close();
                return false;
            }
        }
    }
}


Usage example:

[HttpGet("checkapi/{text}")] 
    public object CheckApi(string text) // returning object automatically converts to JSon
    {
        MySqlCommand C = new MySqlCommand("SELECT * FROM api WHERE apikey = @apikey");
        List&lt;MySqlParameter&gt; collection = new List&lt;MySqlParameter&gt;()
        {
            new MySqlParameter() { ParameterName = "@apikey", Value = text }
        };
        return mysqlWrapper.RunSelectCommand(C, collection);
    }
As you suspected, this code is pretty bad. You are returning three different types of data here. Just, don't.

1)


try
{
    conn.Open();
}
catch (MySqlException ex)
{
    return ex;
}



Don't return the exception, re-throw it and catch it in the caller.

try
{
    conn.Open();
}
catch (MySqlException ex)
{
    throw;
}


In this block, you are catching the exception, then returning the exception to the user as a piece of data. A better way to do this would be to just not catch the exception and let the caller catch it:

try
{
    return mysqlWrapper.RunSelectCommand(C, collection);
}
catch (Exception ex)
{
    return ex;
}


However, now you are exposing your call stack to the user, which you don't want to do. This information could provide hints to someone trying to break into your system, and is not allowed under some security protocols (SOC 2, for example). Instead of returning the whole exception, build a new piece of data and return just the relevant bits (or if they just need one piece, then just return that piece).

2)

Don't return false. Either return an empty object (if the caller doesn't care if there were no results), or throw an exception. Alternately, you could use a ValueTuple and return (bool success, Dictionary&lt;string, string&gt; data) from the method. The first successful path would return (true, {data}) and the second would return (false, null).

3)

You might have a SQL Injection attack going on here. Check out what happens if the client sends a request with the text parameter "test' or 1 = 1 --". It looks like the resulting query might be SELECT * FROM api WHERE apikey = 'test' or 1 = 1 --', but I don't know this well enough to be sure.