Question

I am implementing a database manager class within my app, mainly because there are 3 databases to connect to one being a local one.

However the return function isn't working, I know the query brings back rows but when it is returned by the class it has 0. What am I missing?

public MySqlDataReader localfetchrows(string query, List<MySqlParameter> dbparams = null)
    {
        using (var conn = connectLocal())
        {
            Console.WriteLine("Connecting local : " + conn.ServerVersion);
            MySqlCommand sql = conn.CreateCommand();
            sql.CommandText = query;
            if (dbparams != null)
            {
                if (dbparams.Count > 0)
                {
                    sql.Parameters.AddRange(dbparams.ToArray());
                }
            }
            MySqlDataReader reader = sql.ExecuteReader();
            Console.WriteLine("Reading data : " + reader.HasRows + reader.FieldCount);
            return reader;
            /*
            using (MySqlCommand sql = conn.CreateCommand())
            {
                sql.CommandText = query;
                if (dbparams != null)
                {
                    if (dbparams.Count > 0)
                    {
                        sql.Parameters.AddRange(dbparams.ToArray());
                    }
                }

                MySqlDataReader reader = sql.ExecuteReader();
                Console.WriteLine("Reading data : " + reader.HasRows + reader.FieldCount);

                sql.Parameters.Clear();
                return reader;
            }*/
        }

    }

And the code to get the results

query = @"SELECT jobtypeid, title FROM jobtypes WHERE active = 'Y' ORDER BY title ASC";
            //parentfrm.jobtypes = db.localfetchrows(query);
            var rows = db.localfetchrows(query);
            Console.WriteLine("Reading data : " + rows.HasRows + rows.FieldCount);
            while (rows.Read()){

            }

These scripts return the following :

Connecting local : 5.5.16
Reading data : True2
Reading data : False0
Was it helpful?

Solution

using (var conn = connectLocal())

You're placing the connection inside a using statement, thus closing and disposing the connection after you get to this line:

return reader;

In other words, when the caller gets the reader back, you've closed the database connection and can't fetch the rows. The connection have to be open while the rows are read.

OTHER TIPS

You want to return a DataReader from within a using-statement which will close the underlying connection implicitely.

Instead of returning the DataReader i would recommend following pattern. You could yield IEnumerable<IDatarecord>.

public IEnumerable<IDataRecord> localfetchrows(string query, List<MySqlParameter> dbparams = null)
{
    using (var conn = connectLocal())
    {
        MySqlCommand sql = conn.CreateCommand();
        sql.CommandText = query;
        if (dbparams != null)
        {
            if (dbparams.Count > 0)
            {
                sql.Parameters.AddRange(dbparams.ToArray());
            }
        }

        conn.Open();
        using (IDataReader rdr = sql.ExecuteReader())
        {
            while (rdr.Read())
            {
                yield return (IDataRecord)rdr;
            }
        }
    }
}

You can call it for example in this way:

var records = localfetchrows(query);
foreach (var rec in records.Take(10))
{ 
     Console.WriteLine("Reading data : " + rec.FieldCount);
}

So you don't need to load all into memory just to take a small subset of it.

You create the reader inside a MySqlConnection using block, when exiting from that block your reader has no connection to use.

A possible solution, but less efficient, is to use the Fill method to get back a dataset. This is not only less efficient, but, if you need to process the datarows, you will find yourself looping again on the rows

public DataSet localfetchrows(string query, List<MySqlParameter> dbparams = null) 
{ 
    DataSet ds;
    using (var conn = connectLocal()) 
    { 
        Console.WriteLine("Connecting local : " + conn.ServerVersion); 
        MySqlCommand sql = conn.CreateCommand(); 
        sql.CommandText = query; 
        if (dbparams != null) 
        { 
            if (dbparams.Count > 0) 
            { 
                sql.Parameters.AddRange(dbparams.ToArray()); 
            } 
        } 
        MySqlDataReader reader = sql.ExecuteReader(); 
        Console.WriteLine("Reading data : " + reader.HasRows + reader.FieldCount); 
        reader.Fill(ds);
        return ds; 
    }
}

Looks to me like you are disposing of the connection before using the reader. Try disposing of the connection only after you are done with the reader.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top