views:

433

answers:

3

Hi,

I'm getting something pretty strange going on when trying to read some data using the MySql .net connector. Here's the code:

IDataReader reader = null;

using (MySqlConnection connection = new MySqlConnection(this.ConnectionString))
{
    String getSearch = "select * from organization";
    MySqlCommand cmd = new MySqlCommand(getSearch, connection);
    cmd.CommandType = CommandType.Text;

    connection.Open();
    reader = cmd.ExecuteReader();

    while (reader.Read())
    {
        // response write some stuff to the screen (snipped for brevity)
    }
}

If I put a breakpoint after the ExecuteReader and expand the results view in Visual Studio (hovering over reader and expanding), I can see the rows returned by the query. If I then let that close and expand the results view again, I get the message 'Enumeration yielded no results'.

It seems as if the contents of the reader are getting reset as soon as they're viewed.

As for what we've tried:
- the SQL runs fine directly on to DB
- Binding the results of the query directly to a datagrid just returns an empty datagrid
- got the latest version of the .net connector
- tried on two different machines to rule out any local errors

So far nothing's worked.

If anyone could offer any ideas or suggestions they would be very much appreciated.

Kev

A: 

Since a datareader reads in information, your using block closes the connection to the reader just after assigning its value to the variable. Here is an article that shows you some examples of code that might get you to where you need to be.

The key is that the connection MUST be open, when trying to read from the reader.

Mitchel Sellers
Hi, thanks for replying. There are a few lines in the app code below the execution of the reader (just a basic while read/response write thing) but the first read never works. As soon as the reader is accessed, it empties. Unless I'm mistaken, the connection is still open at this point.
Kevin Wilson
In your example, when the using statement ends, the connection is closed. So if it is outside of the Using block, the connection is closed
Mitchel Sellers
Hi, yes, I should have added that into the code sample. I've done so now; sorry for the confusion.
Kevin Wilson
Ah, with that in mind, I'm going to believe that Bogdan is correct on this one, but I've never experienced what he is saying. SImple way to test is to set a breakpoint somewhere inside the while loop.
Mitchel Sellers
+2  A: 

Hello Kevin, from what I understand the SqlDataReader is intended to be used for a one-time enumeration of the data you've returned. Once you've cycled through the results once, the object has done its duty. Here are a couple ideas for working around this, one or the other of which may solve this for you depending on your needs:

  1. Re-execute the query to generate another SqlDataReader when needed

  2. Instead of using the SqlDataReader, store the results of your original query into a System.Data.DataTable, where you can then re-read and manipulate the data however you like.

Hope this helps!

Adam

Adam Alexander
Thanks for the reply. That makes sense, yes. Been looking at this for hours and that never occurred. I tried running it without pausing to make sure it only reads once but didn't have any luck. It may be something else though but, as I'm now 11 hours into an 8 hour day, I'll have to test tomorrow.
Kevin Wilson
Yep, that was the problem. May thanks.
Kevin Wilson
A: 

Hi, Here is the explanation:

This is because, you have already looped through the reader once in the debugger (the first time you expanded the view). This is the way the readers work, and from what I know, there is no way to reset a reader to go and read again from the beginning, excepting the re-execution option:

You just have to run again the cmd.ExecuteReader(); line (by right click in the source and using "set next statement" menu option).

This is the behaviour of data readers. If you have already looped through it, you cannot go back. You have to execute the command again and retrieve a new one.

If you need to use your data after closing the reader, you might choose to use a Typed DataSet, or the untyped DataSet as specified in Adam's answer.

By the way, here are some optimizations you could make:

  • Move the reader inside the Connection using block to make it go out of scope after finishing using it (once you are out the using block, the connection will be closed and you won't be able to use it anyway, so it doesn't make sense leaving it outside)
  • Run ExecuteReader in another using block (as it implements IDisposable) and do the same thing with the Sql Command (the same IDisposable interface)
  • Don't retrieve all the fields from the database
Bogdan Maxim