views:

349

answers:

3

I'm executing a number of SQL query's as a batch and then getting all of the result sets back in a batch. The way that my code is currently put together, the first result set gets skipped. Now that I know this, I could simply throw in another statement outside of my loop that grabs the first result, however I'm wondering if there is a more elegant solution to this problem.

Here is some sudo code of whats going on:

DbDataReader reader= /*some stuff that returns a batch of results...*/;

while (reader.NextResult())
{
   while (reader.Read())
   {
       if (!reader.IsDBNull(0))
       {
           //do things with the data....
       }
   }
}

Now i would have expected that NextResult() advances you to the first result the first time you call it, which is what Read() seems to do. However what it actually seems to do is bring you to the second result on the first call. Am I misunderstanding how you're expected to use this method, or are you really expected to do some like the following:

DbDataReader reader= /*some stuff that returns a batch of results...*/;

//this deals with the row in the the very first result
while (reader.Read())
{
    if (!reader.IsDBNull(0))
    {
        //do things with the data....
    }
}

//this deals with the rest of the rows...
while (reader.NextResult())
{
   while (reader.Read())
   {
       if (!reader.IsDBNull(0))
       {
           //do exact same things with the data....
           //is this not pretty klugey?
       }
   }
}

This strikes me as rotten programming style, but I don't see a way around it. Does anyone know of a more elegant solution to this?

+3  A: 

In the great majority of cases, you will only be returning a single result set with any given call so it would not make sense for the designers to have required a "NextResultSet" every time you use a reader.

Thus, your second example does indeed hold if you are pulling multiple result sets. The other thing that your post makes me wonder, though, is why you'd be doing the "exact same things with the data" if you are retrieving multiple result sets - wouldn't the structure of the data be different enough that you wouldn't be doing the exact same things?

That is, your example makes me wonder if you don't have some kind of bug in your thinking about how the data management functions work.

Mark Brittingham
Not necessarily: I have a generic procedure that connects to our db, runs some queries from a file, and knows how to output the results to a different file, in a very generic way regardless of the format for the results.
Joel Coehoorn
Good explanation for why they work differnt, though: upvote.
Joel Coehoorn
point taken, mark but in my case there is enough metadata in the results that i pull that i can decide what im doing with them on the fly. thats more or the less the contents of the inner most loop which i omitted.
sweeney
also, i have to disagree with that design decision, in JDBC drivers the nextResult method behaves in the same fashion as the read() method, which to me is more intuitive.
sweeney
Ok - sounds fair. I don't know how experienced you are and sometimes you have to help people by seeing past their immediate problem and into the *why* they are taking the approach that they are. Doesn't sound like you need that though.
Mark Brittingham
Yea, i'm kinda green to be fair, and I do understand your concern. However the code runs acceptably fast despite the inefficiency of that batch of query's and it allows for a certain flexibility in design where I can readily add more querys and deal with them all automatically with no extra coding.
sweeney
+6  A: 

Simply put the NextResult at the end of the loop instead of the beginning:

do {
   while (reader.Read()) {
      if (!reader.IsDBNull(0)) {
         //do things with the data....
      }
   }
} while (reader.NextResult());
Guffa
beat me by 4 seconds!
Joel Coehoorn
well i feel silly - thanks i dunno why i never thought of that...
sweeney
I'm still wondering whether sweeney shouldn't go deeper in thinking about this one though. I can't think of too many situations where I'd pull multiple data sets and do the exact same thing with them.
Mark Brittingham
anyhow, i implemented your do while loop and it runs like w/o error so thanks!
sweeney
A: 

I usually do this:

if(reader.HasRows)
    {
      while(reader.Read())
       {

          // Do Stuff
       }
    }

Hope it helps

MRFerocius
You're misunderstanding the problem, I think. The question was not whether or not the reader had rows, but whether or not it had numerous result sets which you can test with NextResult(). Then you test each result set for numerous rows with Read().
sweeney