I've always thought HasRows was utterly useless, though I admit to having used it once or twice. Whenever I used it, I always asked myself, "self, why are you using this?" to which I answered, "I have no idea, but I'm doing it anyways."

If you call .Read, you get a True or False. If you get False, then there are no rows left, whereas if you call True, then you have moved to that next row. The thing is, you can't do much of anything with a datareader until you DO move to that first row, so call .Read. If there are any rows, you move to the first row, which you'd have to do anyways, and if there are no rows, then you know that HasRows would also be false. So, it seems to me that HasRows is the same as .Read, except that it doesn't ALSO advance you to the next row.