14

Is there a way to check if I'm on the last record ? thanks

wben
  • 247
  • 2
  • 7
  • 20

6 Answers6

21

Use this pattern to identify and process the last row in result:

if (reader.Read())
{
    var loop = true;
    while (loop)
    {
        //1. Here retrive values you need e.g. var myvar = reader.GetBoolean(0);
        loop = reader.Read();
        if (!loop)
        {
            //You are on the last record. Use values read in 1.
            //Do some exceptions
        }
        else {
            //You are not on the last record.
            //Process values read in 1., e.g. myvar
        }
    }
}
Arjan Einbu
  • 13,543
  • 2
  • 56
  • 59
Raman Zhylich
  • 3,537
  • 25
  • 23
  • 4
    Just we have to replace if(reader.Read()) with if(reader.HasRow) – wben Jul 29 '12 at 18:27
  • 2
    @wben In this case you won't be able to read values at the beginning of the first iteration. – Raman Zhylich Jul 30 '12 at 08:58
  • 4
    Wrong. As your code is now, the first row returned is even being skipped. You're setting the reader to the first record in `if (reader.Read())` and then you set `loop = reader.Read()` which directly sets the reader to the second record. Still your solutions provides a proper pattern to how you the problem can be solved. – Thorsten Dittmar Mar 16 '15 at 13:57
  • 2
    @ThorstenDittmar If you actually read the code comments, he's not skipping the first record. He advances to the first record in the if statement, then reads the values, then sets loop = reader.Read() which is the second record. – user2966445 Feb 24 '17 at 21:36
  • You are right, but the code sample is very misleading the way it is formatted now. – Thorsten Dittmar Feb 25 '17 at 07:35
5

Other than "there isn't another one afterwards", no. This may mean you need to buffer the row, try to read, then look at the buffered data if it turned out to be the last.

In many cases, when the data is moderate and you are building an object model of some kind, you can just looks at the constructed data, i.e. make a List<T> of all the rows when using the reader, then after that, look at the last row in the list.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Yeah , but I don't want to pass on two loops !! – wben Jul 28 '12 at 17:59
  • @wben if it is in a list, looping is insanely cheap - or just access by indexer: `list[list.Count-1]`. Of course, buffering the previous row is even cheaper, but more complex. – Marc Gravell Jul 28 '12 at 18:48
  • @wben to make things clearer, in the accepted answer, where is says "        //1. Here retrive values you need e.g. var myvar = reader.GetBoolean(0);", that is what I/we mean by "buffer the row, try to read, then look at the buffered data if it turned out to be the last". The code example makes it clearer, of course. – Marc Gravell Jul 28 '12 at 18:50
1

To iterate through the SqlDataReader:

SqlDataReader reader = ...;
while(reader.Read())
{
    // the reader will contain the current row
}

There's nothing in the reader telling you it's the last row. If you still need to get on the last row, perhaps storing the row's data in a seperate variable you can get that data after exiting the loop.

Other alternatives would be:

  • to get the data into a DataSet/DataTable
  • to store the data in a list/array
  • retrieve the data in reverse order (rewrite your query), so that the first row is the one you want.
Arjan Einbu
  • 13,543
  • 2
  • 56
  • 59
1

Another possibility would be to put the information into the data set.

You are reading the data using a query. Let's call it q. Use this query instead:

select row_number() over (order by (select NULL)) as seqnum,
       count(*) over (partition by null) as numrecs
       q.*,
from (<q>) q
order by seqnum

Now the last record has seqnum = numrecs, which you can test for in your application.

By the way, this assumes that you are retrieving the data in an unordered way. If you want ordering, put the criteria in the "order by" clause for row_number().

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
0
  1. As you know, a SQLDataReader doesn't have a "row count" property. You just read until EOF.

  2. However, a DataSet does. Perhaps you can substitute a DataAdapter and some kind of data set or table:

paulsm4
  • 114,292
  • 17
  • 138
  • 190
0

You can't do that without repeating yourself i.e. fetching the record twice. Here is a shorter method

System.Data.DataTable dt = new System.Data.DataTable();
dt.Load(myDataReader);
int recordCount = dt.Rows.Count;
if(recordCount > 0)
{
   if(dt.Rows[recordCount-1]["username"] == "wrong value")
     throw new Exception("wrong value");
}

I wrote this off-hand so it's not tested but that's the approach

codingbiz
  • 26,179
  • 8
  • 59
  • 96