2008-09-25 25 views
5

Khi cố gắng gọi Close hoặc Dispose trên một SqlDataReader tôi nhận được một thời gian chờ hết hạn ngoại lệ. Nếu bạn có một DbConnection đến SQL Server, bạn có thể tái tạo nó cho mình với:.NET: SqlDataReader.Close hoặc .Dispose results in Timeout Expired exception

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(); 

Nếu bạn gọi reader.Close() hoặc reader.Dispose() nó sẽ ném một System.Data.SqlClient.SqlException:

  • ERRORCODE: -2146232060 (0x80131904)
  • nhắn: "Thời gian chờ hết hạn Khoảng thời gian chờ trôi qua trước khi hoàn thành các hoạt động hoặc các máy chủ không được đáp ứng.."

Trả lời

13

đó là vì bạn vừa mở trình đọc dữ liệu và chưa hoàn toàn lặp lại qua trình đọc dữ liệu. bạn sẽ cần phải .Cancel() đối tượng DbCommand của bạn trước khi bạn cố gắng đóng một trình đọc dữ liệu chưa hoàn thành (và cả DbConnection). Tất nhiên, bởi .Cancel() - ing DbCommand của bạn, tôi không chắc chắn về điều này nhưng bạn có thể gặp phải một số ngoại lệ khác. nhưng bạn chỉ nên nắm bắt nó nếu nó xảy ra.

0

Bạn thực sự đọc dữ liệu ở đâu? Bạn chỉ đang tạo một trình đọc, nhưng không đọc Dữ liệu. Nó chỉ là một phỏng đoán nhưng có lẽ người đọc có vấn đề đóng cửa nếu bạn không đọc;)

DbDataReader rdr = cmd.ExecuteReader(); 
while(rdr.Read()) 
{ 
    int index = rdr.GetInt32(0); 
} 
+0

vấn đề xảy ra nếu bạn đọc zero hàng, một hàng hoặc nhiều hàng. –

2

Cruizer có câu trả lời: gọi command.Cancel():

using (DbCommand cmd = connection.CreateCommand()) 
{ 
    cmd.CommandText = sql; 
    using (DbDataReader rdr = cmd.ExecuteReader()) 
    { 
     while (rdr.Read()) 
     { 
      if (WeShouldCancelTheOperation()) 
      { 
      cmd.Cancel(); 
      break; 
      } 
     } 
    }  
} 

Nó cũng rất hữu ích để biết rằng bạn có thể gọi Hủy bỏ ngay cả khi người đọc đã đọc tất cả các hàng (tức là nó không ném một số "không có gì để hủy bỏ" ngoại lệ.)

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(); 
}