Error: Invalid attempt to call Read when reader is closed after the while loop?

不想你离开。 提交于 2019-12-12 10:27:52

问题


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


回答1:


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.




回答2:


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




回答3:


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



来源:https://stackoverflow.com/questions/14873618/error-invalid-attempt-to-call-read-when-reader-is-closed-after-the-while-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!