IDataReader empties when viewing for a second time
-
06-07-2019 - |
Question
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.
Solution
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:
Re-execute the query to generate another SqlDataReader when needed
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
OTHER TIPS
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.
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 anotherusing
block (as it implementsIDisposable
) and do the same thing with the SqlCommand
(the sameIDisposable
interface) - Don't retrieve all the fields from the database