简体   繁体   中英

SQL returning incorrect amount of rows

I am trying to get 2 rows of data from my MS Access Database using an SQL command and using the datareader but it's only returning one row of data. I don't exactly know how the datareader works so I think it might be from something I incorrectly coded with it. The SQL command should be fine cause I when I run it in an MS Access Query it works. Do you know what is wrong with my code? [Edit: I am not actually trying to get the number of rows, that's just for testing. Below the code snippet I posted, my program actually loads the data into an array so that the 2 integers can be compared and the smallest one is chosen.]

if (passageID != 1)
        {
            Connect(fileName);

            OleDbCommand com = new OleDbCommand();
            com.Connection = cxn;
            com.CommandText = "SELECT PO.OptionID_FK FROM PassageOption AS PO WHERE PO.PassageID_FK = @passageID;";
            com.Parameters.AddWithValue("@passageID", passageID);


            OleDbDataReader r = com.ExecuteReader();

            int numRows = r.RowCount;

            if (r.HasRows)
            {
                int i = 0;
                int[] optionIDs = new int[2];

                while (r.Read())
                {
                    optionIDs[i] = (int)r[i]; // It gives me the following error, the second time it runs, when i = 1; System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'
                    i++;
                }

                if (optionIDs[0] < optionIDs[1])
                {
                    j = optionIDs[0];
                }
                else
                {
                    j = optionIDs[1];
                }
            }
        }

A datareader doesn't know how many rows will be returned by your select query until it has read all the data from the underlying stream coming from the database.

The FieldCount property returns the number of fields in your query and it is exactly one for your current query.

To know the rows you need to Read them one by one or use a DataTable

int numRows = 0;
while(r.Read())
{
    // do your task with the current IDataRecord
    numRows++;
}

Console.WriteLine($"There are {numRows} rows");

Or filling a DataTable

DataTable dt = new DataTable();
dt.Load(com.ExecuteReader());
Console.WriteLine($"There are {dt.Rows.Count} rows");

The two methods above are useful if you plan to use the data returned (in the reader array or in the table rows array), but if you just want to know how many rows exists then it is better (albeit minimal with only two rows returned) to change your query to:

com.CommandText = @"SELECT COUNT(*) FROM PassageOption AS PO 
                    WHERE PO.PassageID_FK = @passageID;";
com.Parameters.AddWithValue("@passageID", passageID);
int numRows = (int)com.ExecuteScalar();

No reader needed when you want one row with one field, just ExecuteScalar

EDIT to update with your last edit

This line fails

optionIDs[i] = (int)r[i]; 

because you have only one field in your query. The indexer i should be used only to refer to the optionIDs array not to extract a field at position 1 from the reader. There is no field at position 1, just use

optionIDs[i] = (int)r[0]; 

for every Read call

int numRows = r.FieldCount;

FieldCount Property gets the number of columns in the row not the number of records.

You are selecting only OptionID_FK single Column from the table. FieldCount will show you 1.

Getting no. of rows

OleDbDataReader r = com.ExecuteReader();
int rowCount = 0;
if (r.HasRows)  
{  
    while (r.Read())  
    {  
       rowCount++;     
    }  
}
r.Close(); 

Your data reader only has one column in it, the column you selected, PO.OptionID_FK . Therefore in your loop, when i is 1:

optionIDs[i] = (int)r[i]; // It gives me the following error, the second time it runs, when i = 1; System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'

...you're trying to select the second column from the datareader ( r[i] ), which doesn't exist.

The way DataReader works is that whenever you do r.read , you're moved onto the next row, and your r "array" variable is refreshed with all the column values from the new row. The array index r[n] selects the nth column of the reader, not the nth row . So you should just use:

optionIDs[i] = (int)r[0];

...which will set your optionIDs value with the value of the DataReader's first (zeroth) column for the current row.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM