2010-03-19 151 views
1

這一個讓我難住。下面是代碼的相對位:ASP.NET SqlDataReader拋出錯誤:讀取器關閉時調用Read的無效嘗試

public AgencyDetails(Guid AgencyId) 
    { 
     try 
     { 
      evgStoredProcedure Procedure = new evgStoredProcedure(); 
      Hashtable commandParameters = new Hashtable(); 
      commandParameters.Add("@AgencyId", AgencyId); 
      SqlDataReader AppReader = Procedure.ExecuteReaderProcedure("evg_getAgencyDetails", commandParameters); 
      commandParameters.Clear(); 

      //The following line is where the error is thrown. Errormessage: Invalid attempt to call Read when reader is closed. 
      while (AppReader.Read()) 
      { 
       AgencyName = AppReader.GetOrdinal("AgencyName").ToString(); 
       AgencyAddress = AppReader.GetOrdinal("AgencyAddress").ToString(); 
       AgencyCity = AppReader.GetOrdinal("AgencyCity").ToString(); 
       AgencyState = AppReader.GetOrdinal("AgencyState").ToString(); 
       AgencyZip = AppReader.GetOrdinal("AgencyZip").ToString(); 
       AgencyPhone = AppReader.GetOrdinal("AgencyPhone").ToString(); 
       AgencyFax = AppReader.GetOrdinal("AgencyFax").ToString(); 
      } 
      AppReader.Close(); 
      AppReader.Dispose(); 
     } 
     catch (Exception ex) 
     { 
      throw new Exception("AgencyDetails Constructor: " + ex.Message.ToString()); 
     } 
    } 

而且ExecuteReaderProcedure執行:

public SqlDataReader ExecuteReaderProcedure(string ProcedureName, Hashtable Parameters) 
    { 
     SqlDataReader returnReader; 

     using (SqlConnection conn = new SqlConnection(connectionString)) 
     { 
      try 
      { 
       SqlCommand cmd = new SqlCommand(ProcedureName, conn); 
       SqlParameter param = new SqlParameter(); 
       cmd.CommandType = System.Data.CommandType.StoredProcedure; 

       foreach (DictionaryEntry keyValue in Parameters) 
       { 
        cmd.Parameters.AddWithValue(keyValue.Key.ToString(), keyValue.Value); 
       } 

       conn.Open(); 
       returnReader = cmd.ExecuteReader(CommandBehavior.CloseConnection); 
      } 
      catch (SqlException e) 
      { 
       throw new Exception(e.Message.ToString()); 
      } 
     } 
     return returnReader; 
    } 

連接字符串作爲工作在同一類運行良好其他存儲過程。唯一的問題似乎是從這個方法返回SqlDataReaders!他們將錯誤消息放在標題中。任何想法都非常感謝!提前致謝!

+0

請發佈完整的例外情況並顯示發生異常的位置。 – 2010-03-19 22:53:34

+0

異常消息是:無法嘗試在閱讀器關閉時調用Read。它發生在這條線上:while(AppReader.Read()) 希望能夠解決問題! – Bugget 2010-03-19 22:55:11

回答

5

A DataReader通常直接連接到數據庫。在這種情況下,當您從該方法返回時,您將從創建SqlConnetion對象的using語句中返回。這將在SqlConnection上調用Dispose,並使SqlDataReader無效。

試試這個:

public SqlDataReader ExecuteReaderProcedure(string ProcedureName, Hashtable Parameters) 
{ 
    SqlConnection conn = new SqlConnection(connectionString); 
    using(SqlCommand cmd = new SqlCommand(ProcedureName, conn)) 
    { 
     cmd.CommandType = System.Data.CommandType.StoredProcedure; 

     foreach(DictionaryEntry keyValue in Parameters) 
     { 
      cmd.Parameters.AddWithValue(keyValue.Key.ToString(), keyValue.Value); 
     } 

     conn.Open(); 
     return cmd.ExecuteReader(CommandBehavior.CloseConnection); 
    } 
} 

這樣稱呼它:

public AgencyDetails(Guid AgencyId) 
{ 
    evgStoredProcedure Procedure = new evgStoredProcedure(); 
    Hashtable commandParameters = new Hashtable(); 
    commandParameters.Add("@AgencyId", AgencyId); 
    using(SqlDataReader AppReader = 
     Procedure.ExecuteReaderProcedure("evg_getAgencyDetails", 
             commandParameters)) 
    { 
     commandParameters.Clear(); 

     while(AppReader.Read()) 
     { 
      AgencyName = AppReader.GetOrdinal("AgencyName").ToString(); 
      AgencyAddress = AppReader.GetOrdinal("AgencyAddress").ToString(); 
      AgencyCity = AppReader.GetOrdinal("AgencyCity").ToString(); 
      AgencyState = AppReader.GetOrdinal("AgencyState").ToString(); 
      AgencyZip = AppReader.GetOrdinal("AgencyZip").ToString(); 
      AgencyPhone = AppReader.GetOrdinal("AgencyPhone").ToString(); 
      AgencyFax = AppReader.GetOrdinal("AgencyFax").ToString(); 
     } 
    } 
} 

using語句AppReader末,AppReader.Dispose將被調用。由於您使用CommandBehavior.CloseConnection調用ExecuteReader,讀者的處置也將關閉連接。

請注意,我擺脫了你的不良異常處理。切勿使用ex.Message,除了可能顯示給最終用戶。其他人都會想要完整的例外。此外,如果您允許傳播完整的異常,則無需將方法名稱作爲異常消息的一部分進行打印。方法名稱將位於堆棧跟蹤中。

+0

你當然是對的!謝謝約翰! – Bugget 2010-03-19 23:00:05

+0

感謝您的一個很好的答案。解決了我的問題。 – ChessWhiz 2010-06-30 21:02:27

相關問題