-1

Hello i have a method which reads some data from the sql and saves them to arrays.

to find out how many rows the sql result has i wrote this:

DataTable dt = new DataTable();
            dt.Load(rdr);
            count = dt.Rows.Count;

after that, the sqldatareader saves the results to arrays.

here is my complete code:

 public BookingUpdate[] getBookingUpdates(string token)
{
    String command = "SELECT b.ID,b.VERANSTALTER, rr.VON ,rr.BIS, b.THEMA, b.STORNO, ra.BEZEICHNUNG from BUCHUNG b JOIN RESERVIERUNGRAUM rr on rr.BUCHUNG_ID = b.ID JOIN RAUM ra on ra.ID = rr.RAUM_ID WHERE b.UPDATE_DATE BETWEEN DATEADD (DAY , -20 , getdate()) AND getdate() AND b.BOOKVERNR = 0";
    SqlConnection connection = new SqlConnection(GetConnectionString());
    BookingUpdate[] bookingupdate = new BookingUpdate[1];
    connection.Open();
    try
    {
        SqlCommand cmd = new SqlCommand(command, connection);
        SqlDataReader rdr = null;
        int count = 0;
        int c = 0;

        rdr = cmd.ExecuteReader();
        DataTable dt = new DataTable();
        dt.Load(rdr);
        count = dt.Rows.Count;
        bookingupdate = new BookingUpdate[count];

        while (rdr.Read())   // <--- HERE COMES THE ERROR
        {
                bookingupdate[c] = new BookingUpdate();
                bookingupdate[c].bookingID = Convert.ToInt32(rdr["ID"]);
                bookingupdate[c].fullUserName = rdr["VERANSTALTER"].ToString();
                bookingupdate[c].newStart = (DateTime)rdr["VON"];
                bookingupdate[c].newEnd = (DateTime)rdr["BIS"];
                bookingupdate[c].newSubject = rdr["THEMA"].ToString();
                bookingupdate[c].newlocation = rdr["BEZEICHNUNG"].ToString();
                if (rdr["STORNO"].ToString() != null)
                {
                    bookingupdate[c].deleted = true;
                }
                else
                {
                    bookingupdate[c].deleted = false;
                }
                c++;

        }
    }

    catch (Exception ex)
    {
        log.Error(ex.Message + "\n\rStackTrace:\n\r" + ex.StackTrace);
    }
    finally
    {
        connection.Close();
    }
    return bookingupdate;
}

the exeption is : Invalid attempt to call Read when reader is closed

Eray Geveci
  • 1,099
  • 4
  • 17
  • 39

3 Answers3

3

The Load-Method closes the DataReader, hence a following call to Read() fails (well, that's excatly what the exception tells you).

Once you read the data into your DataTable, you could simply query it and use a Select projection to create your BookingUpdate instances (no need for the while-loop/BookingUpdate[]). So your code can basically trimmed down to

String command = "SELECT b.ID,b.VERANSTALTER, rr.VON ,rr.BIS, b.THEMA, b.STORNO, ra.BEZEICHNUNG from BUCHUNG b JOIN RESERVIERUNGRAUM rr on rr.BUCHUNG_ID = b.ID JOIN RAUM ra on ra.ID = rr.RAUM_ID WHERE b.UPDATE_DATE BETWEEN DATEADD (DAY , -20 , getdate()) AND getdate() AND b.BOOKVERNR = 0";
SqlCommand cmd = new SqlCommand(command, new SqlConnection(GetConnectionString()));
connection.Open();

DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());

var bookingupdate = dt.Rows.OfType<DataRow>().Select (row => 
                    new BookingUpdate
                    {
                        bookingID = Convert.ToInt32(row["ID"]),
                        fullUserName = row["VERANSTALTER"].ToString(),
                        newStart = (DateTime)row["VON"],
                        newEnd = (DateTime)row["BIS"],
                        newSubject = row["THEMA"].ToString(),
                        newlocation = row["BEZEICHNUNG"].ToString(),
                        deleted = row["STORNO"].ToString() != null // note that this line makes no sense. If you can call `ToString` on an object, it is not 'null'
                    }).ToArray();

return bookingupdate;

(Note: I omited the try-block for readability)

You may also want to look into the DataRowExtensions, especially the Field method, to make your code more readable.

sloth
  • 99,095
  • 21
  • 171
  • 219
1

DataTable.Load(IDataReader) closes reader after loading data from it. Use DataTable to get data you loaded.

gzaxx
  • 17,312
  • 2
  • 36
  • 54
0

You have already processed the reader at the following line due to which reader is at EOF/Closed:

dt.Load(rdr);

If you want to process the records after above method call, you should make use of your created DataTable object dt by above line unsing for loop with dt.Rows.Count instead of while (rdr.Read())

Checkout this topic from MSDN

S2S2
  • 8,322
  • 5
  • 37
  • 65