错误:在while循环后关闭阅读器时无效尝试调用Read?

您好我有一个方法从sql读取一些数据并将它们保存到数组。

找出sql结果有多少行我写了这个:

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

之后,sqldatareader将结果保存到数组中。

这是我的完整代码:

  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; } 

例外情况是:读取器关闭时无效尝试调用Read

Load -Method关闭了DataReader ,因此对Read()的后续调用失败了(好吧,这就是exception告诉你的内容)。

一旦您将数据读入DataTable ,您只需查询它并使用Select投影来创建您的BookingUpdate实例(不需要while -loop / BookingUpdate[] )。 所以你的代码基本上可以减少到

 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().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; 

(注意:为了便于阅读,我省略了try-block)

您可能还需要查看DataRowExtensions ,尤其是Field方法,以使代码更具可读性。

DataTable.Load(IDataReader)在从中加载数据后关闭阅读器。 使用DataTable获取您加载的数据。

您已经在以下行处理了阅读器,因为哪个阅读器处于EOF/Closed

 dt.Load(rdr); 

如果你想在上面的方法调用之后处理记录,你应该使用你创建的DataTable对象dt通过上面的行unsing for循环使用dt.Rows.Count 而不是 while (rdr.Read())

从MSDN查看此主题