你好,我有一个方法可以从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 + "nrStackTrace:nr" + ex.StackTrace);
}
finally
{
connection.Close();
}
return bookingupdate;
}
示例为:读取器关闭时调用Read的尝试无效
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;
(注意:为了可读性,我省略了try块)
您可能还想研究DataRowExtensions
,尤其是Field
方法,以使代码更具可读性。
DataTable.Load(IDataReader)
加载数据后关闭读卡器。使用DataTable
获取您加载的数据。
由于哪个读卡器位于EOF/Closed
:,您已经在以下行处理了读卡器
dt.Load(rdr);
如果您想在上面的方法调用后处理记录,则应该使用您创建的DataTable
对象dt
,方法是在上面用dt.Rows.Count
而不是while (rdr.Read())
的取消循环
从MSDN 中签出此主题