原因:單一 SqlConnection 同一時間只能關聯一個開啟的 SqlDataReader。忘記關閉第一個 Reader 再嘗試開啟第二個即拋出此異常。
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Person";
SqlDataReader reader1 = cmd.ExecuteReader();
while (reader1.Read()) { /* ... */ }
// 忘記 reader1.Close()
cmd.CommandText = "SELECT * FROM Course";
SqlDataReader reader2 = cmd.ExecuteReader(); // 拋出異常
while (reader2.Read()) { /* ... */ }
實際專案中代碼層層封裝,異常拋出時難以知道是哪個 Reader 未關閉。
SqlConnection 無公開 API 取得當前開啟的 Reader,但內部成員可助一臂之力:
SqlConnection.GetOpenConnection() → SqlInternalConnectionSqlInternalConnection.FindLiveReader(SqlCommand command) → SqlDataReaderSqlDataReader.Command → 關聯的 SqlCommand透過 Reflection 呼叫上述 Internal 方法/屬性,即可在捕捉異常時找出「正在佔用連線的 Reader」並記錄其堆疊資訊,快速定位 Bug。