views:

203

answers:

2

My problem is that this does not work;

while (reader.Read())
{
   if (reader.NextResult() == true)
   {
      json.AppendFormat("{{\"AvgDate\": \"{0}\"}},{{\"MarkerID\": \"{1}\"}},", reader["AvgDate"], reader["MarkerID"]);
   }

But this works;

while (reader.Read())
{
    json.AppendFormat("{{\"AvgDate\": \"{0}\"}},{{\"MarkerID\": \"{1}\"}},", reader["AvgDate"], reader["MarkerID"]);
}

The problem with the first one is that the reader doesn't find any data to read. I get;

"Invalid attempt to read when no data is present."

Can anyone see why?

+11  A: 

NextResult() makes the reader advance to the next result set coming back from the query. The way you have it written, it would skip the first result set (likely the only one).

The pattern I think you want is:

if (reader.HasRows)
{
     do
     {
        while (reader.Read())
        {
             ...
        }
     }
     while (reader.NextResult());
}

This will check if there are any results, and if so, read the results in each result set until there are no more left to read.

EDIT: Based on comment:

For JSON, consider using a list of temporary objects, then a DataContractJsonSerializer:

 public class DateClass
 {
      public string AvgDate { get; set; }
      public int MarkerID { get; set; }
 }

 ...

 var dates = new List<DateClass>();
 if (reader.HasRows)
 {
       while (reader.Read())
       {
           var date = new DateClass { AvgDate = reader["AvgDate"].ToString(), MarkerID = (int)reader["MarkerID"] };
            dates.Add( date );
       }
 }

 var stream = new MemoryStream();
 var serializer = new DataContractJsonSerializer( typeof(DateClass) );
 serializer.WriteObject( stream, dates );
 stream.Seek( 0, SeekOrigin.Begin );
 return stream.ToString();
tvanfosson
+1. Clarifying, a "resultset" can be thought of as a table. NextResult() is only necessary when your SQL statement returns multiple tables.
David Stratton
Ahh, I see. That explains things. However there is no HasResults method for this class. Any suggestion on how to proceed without one? I can't find any useful method actually, but maybe I'm overlooking something
cc0
@cc0 - Yea the correct function is reader.HasRows() not HasResults(). It tells you if your resultset returned any rows or not. If no rows are returned and you do a reader.Read() you will get an exception, so always have to check for reader.HasRows() before calling the reader.Read() function.
jaywon
@jaywon - nice catch. It's been awhile since I've used SqlDataReader and I neglected to look it up when typing my answer. It' also a property, not a method. So much for my memory.
tvanfosson
Ah, thanks guys, this clarifies things. However what I'm trying to do is avoid that a comma is added at the end, when the final reader entry is printed. I'm still not sure how to accomplish that. Any ideas?
cc0
I'll add an idea on how to do that.
tvanfosson
@tv - oops. yes you are correct HasRows is a property. i also did not look it up. don't feel so bad tho knowing the big dogs still make the same mistakes. homer simpson effect :p
jaywon
Lol, well anyway. Just to add what I figured out here on how to simply remove the last part of a string. *drum roll* TrimEnd()! Worked like a charm.
cc0
+3  A: 

NextResult takes you to the next Result Set from the Reader. You probably only have one Result Set.

Jacob G