您好我有一个方法从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的无效尝试
答案 0 :(得分:3)
Load
- 方法会关闭DataReader
,因此对Read()
的跟随调用失败(嗯,这是异常告诉您的内容)。
将数据读入DataTable
后,您只需查询并使用Select
投影即可创建BookingUpdate
个实例(无需while
- 环路/ 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<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;
(注意:为了便于阅读,我省略了试用块)
您可能还想查看DataRowExtensions
,尤其是Field
方法,以使您的代码更具可读性。
答案 1 :(得分:1)
DataTable.Load(IDataReader)
在从中加载数据后关闭读者。使用DataTable
获取您加载的数据。
答案 2 :(得分:0)
由于哪个读者位于EOF/Closed
:
dt.Load(rdr);
如果您想在上述方法调用之后处理记录,应该使用您创建的DataTable
对象dt
通过上面的行unsing for {{1而{em>代替 dt.Rows.Count
从MSDN
查看此主题