正在寫一段由SqlDataReader取回資料逐一處理的程式,由於資料筆數很多,我就用了以下的程式,先小小Read()個三筆試算,就Close SqlDataReader及SqlConnection結束作業。
static void Test()
{ using (SqlConnection cn =
new SqlConnection("Data Source=mySql; User Id=blah; Password=blahblah; Initial Catalog=MyDB;"))
{ cn.Open();
int i = 0;
SqlCommand cmd = new SqlCommand(
"SELECT * FROM BigTable", cn);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read() && i < 3)
{ Console.WriteLine(dr["Col1"].ToString());
/* Do something... */
i++;
}
dr.Close();
cn.Close();
}
}
不管我Read()幾次,Client與SQL Server間的往來封包數都跟全部讀完一樣多。也就是說,SqlDataReader.Close()的同時,會將沒讀完的資料全部傳完。
看來為了要計算RecordsAffected,SqlDataReader會堅持將全部資料讀完。在ADO時代,ForwardOnly Recordset的一大特點就是無法得知總筆數RecordCount。而我一直把DataReader當成ForwardOnly Recordset的傳人,想也想不到它會對計算資料筆數這麼堅持,這是所謂的"青出於藍"嗎? (摩亞風)
總之,因資料筆數在此完全沒用,我們可以依文件的建議,在dr.Close()前加上個cmd.Cancel(),就可避免不必要的統計操作。測了一下,加了cmd.Cancel之後,SqlDataReader果然就不再愚公移山了,不論SELECT母體大小為何,往來的封包數改由dr.Read()的次數決定。