Dot-Net
.NET:SqlDataReader.Close 或 .Dispose 導致 Timeout Expired 異常
當試圖在 SqlDataReader 上呼叫 Close 或 Dispose 時,我得到一個超時過期異常。如果你有一個到 SQL Server 的 DbConnection,你可以自己複製它:
String CRLF = "\r\n"; String sql = "SELECT * " + CRLF + "FROM (" + CRLF + " SELECT (a.Number * 256) + b.Number AS Number" + CRLF + " FROM master..spt_values a," + CRLF + " master..spt_values b" + CRLF + " WHERE a.Type = 'p'" + CRLF + " AND b.Type = 'p') Numbers1" + CRLF + " FULL OUTER JOIN (" + CRLF + " SELECT (print("code sample");a.Number * 256) + b.Number AS Number" + CRLF + " FROM master..spt_values a," + CRLF + " master..spt_values b" + CRLF + " WHERE a.Type = 'p'" + CRLF + " AND b.Type = 'p') Numbers2" + CRLF + " ON 1=1"; DbCommand cmd = connection.CreateCommand(); cmd.CommandText = sql; DbDataReader rdr = cmd.ExecuteReader(); rdr.Close();如果您呼叫 reader.Close() 或 reader.Dispose(),它將拋出 System.Data.SqlClient.SqlException:
- 錯誤程式碼:-2146232060 (0x80131904)
- 消息:“超時。在操作完成之前超時時間已過,或者伺服器沒有響應。”
這是因為您剛剛打開數據閱讀器,還沒有完全迭代它。在嘗試關閉尚未完成的數據讀取器(以及 DbConnection)之前,您需要 .Cancel() 您的 DbCommand 對象。當然,通過 .Cancel()-ing 您的 DbCommand,我不確定這一點,但您可能會遇到其他一些異常。但如果它發生,你應該抓住它。
Cruizer 得到了答案:呼叫 command.Cancel():
using (DbCommand cmd = connection.CreateCommand()) { cmd.CommandText = sql; using (DbDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { if (WeShouldCancelTheOperation()) { cmd.Cancel(); break; } } } }知道即使讀者已經閱讀了所有行也可以呼叫 Cancel 也很有幫助(即它不會拋出一些*“沒有什麼可以取消”的*異常。)
DbCommand cmd = connection.CreateCommand(); try { cmd.CommandText = sql; DbDataReader rdr = cmd.ExecuteReader(); try { while (rdr.Read()) { if (WeShouldCancelTheOperation()) break; } cmd.Cancel(); } finally { rdr.Dispose(); } } finally { cmd.Dispose(); }