2012-10-29 101 views
0

我在不同的類中有幾個代碼部分,它們使用此代碼或非常相似的代碼從SQL Server數據庫中提取一些數據。他們中的大多數工作,但我遇到了幾個問題,真的不明白爲什麼。上面的代碼將執行60-64次,檢索行,但隨後出現無效的讀取錯誤。我追查記錄中的任何暗示,但它似乎只是在這些記錄和停止之間的任何地方。從這個類沒有任何其他類的函數調用,實質上,這是onyl的東西在運行。無效嘗試調用讀取器關閉時讀取

我的連接字符串有600秒的時間,我也設置了mars。另一個說明;這是從一個Parallel.ForEach調用並行度設置爲2.

正如我所說的,我通過程序在多個地方使用這種結構的代碼,其中大部分工作很好,令我擔心的不僅僅是錯誤,但其發生的不一致。

當我擺脫了Parallel.ForEach,只是運行它爲foreach,它的工作原理。我需要那些線程,或者這需要太長時間。我也很好奇讀者正在關閉的地方。

異常:System.InvalidOperationException - 讀取器關閉時調用Read的無效嘗試。

稱爲碼:

public string GetUnderwritingType(string id) 
    { 
     UnderwritingType uwt = new UnderwritingType(); 
     GetRequiredPercent(id, ref uwt); 
     GetParticipation(id, ref uwt); 
     return CalculateUnderwritingType(ref uwt); 
    } 
    private void GetRequiredPercent(string id, ref UnderwritingType uwt) 
    { 
     DataCommon common = new DataCommon(Settings.Default.ReqPercentSP, id); 
     try 
     { 
     /******* Error on this reader statement ********/  
using (SqlDataReader reader = common.Command.ExecuteReader(CommandBehavior.CloseConnection))    { 
       /* no data */ 
       if (reader.HasRows == false) return; 
       while (reader.Read()) 
       { 
        uwt.RequiredPercent.Add(Double.Parse(reader[REQ_PERCENT_FIELD].ToString())); 
        uwt.MinimumCount.Add(Int32.Parse(reader[MIN_COUNT_FIELD].ToString())); 
        uwt.UWType.Add(Int32.Parse(reader[UW_LEVEL_FIELD].ToString())); 
       } 
      } 
     } 
     catch (InvalidOperationException) 
     { 
      if (common.Connection.State == ConnectionState.Open) common.Connection.Close(); 
      throw; 
     } 
     catch (SqlException) 
     { 
      if (common.Connection.State == ConnectionState.Open) common.Connection.Close(); 
      throw; 
     } 
    } 

代碼,設置了連接:

public class DataCommon 
    { 
     private readonly SqlCommand _command; 
     private SqlConnection _connection; 

     public DataCommon(string storedProcedure, string id) 
     { 
      SetConnection(); 
      _command = new SqlCommand(storedProcedure, Connection); 
      if (_command != null) _command.CommandType = CommandType.StoredProcedure; 
      _command.Parameters.Add("@Id", SqlDbType.NVarChar).Value = id; 
     } 
     /// <summary> 
     /// Gets the database connection. 
     /// </summary> 
     public SqlConnection Connection 
     { 
      get { return _connection; } 
     } 
     /// <summary> 
     /// Gets the database command object. 
     /// </summary> 
     public SqlCommand Command 
     { 
      get { return _command; } 
     } 
     /// <summary> 
     /// Sets the database connection. 
     /// </summary> 
     private void SetConnection() 
     { 
      _connection = new SqlConnection {ConnectionString = Settings.Default.TestConnection}; 
      _connection.Open(); 
      if (_connection.State != ConnectionState.Open) 
       throw new DataException(Settings.Default.ConnectionErrorMessage); 
     } 
    } 

連接字符串:數據源= XXXXX;初始目錄= YYYYY; Trusted_Connection = TRUE; MultipleActiveResultSets = True; Connection Timeout = 600;

堆棧跟蹤: .Data.SqlClient.SqlDataReader.ReadInternal(布爾的setTimeout) 在System.Data.SqlClient.SqlDataReader.Read() 在GroupDataAccess.EligibilityClassData.GetEligibilityClass(字符串ID)在C:\ Subversion \ branches \ Fimmas \ FimmasToInfoHub \ GroupHubFeed \ GroupData \ EligibilityClassData.cs:第95行 位於C:\ Subversion \ branches \ Fimmas \ FimmasToInfoHub \ GroupHubFeed \ GroupLogic \ GroupExtract中的GroupLogic.GroupExtract.BuildEligibilityClass(String id,Group & group) .cs:第188行 位於GroupLogic.GroupExtract。 <> C_ DisplayClass2.b _1()在C:\顛覆\分支\ Fimmas \ FimmasToInfoHub \ GroupHubFeed \ GroupLogic \ GroupExtract.cs:在System.Threading.Tasks.Task.InnerInvoke(線113 ) 在系統。 Threading.Tasks.Task。執行()

初始呼叫通過循環(轉換爲正常的foreach,萬物精):

ParallelOptions options = new ParallelOptions(); 
options.MaxDegreeOfParallelism = 2; 
Parallel.ForEach(ids, options, id => BuildGroup(id)); 

電話

private void BuildGroup(string id) 
{ 
    Group[] group = { new Group() }; 
    Task eligibilityBlock = Task.Factory.StartNew(() => 
              BuildEligibilityClass(id, ref @group[0])); 
      Task.WaitAny(eligibilityBlock); 
      GroupList.Add(@group[0]); 
} 

其中要求

private static void BuildEligibilityClass(string id, ref Group group) 
    { 
     EligibilityClassData eligClassData = new EligibilityClassData(); 
     group.EligibilityClassList = eligClassData.GetEligibilityClass(id); 

    } 

其中一個讀入。

+2

我認爲這是完成第一併聯關閉連接,第二無法讀取,您使用using語句中CommandBehavior.CloseConnection。儘量不要關閉連接,但只有讀者。並行代碼完成後,關閉與數據庫的連接。 –

+1

你可以顯示「BuildGroup」的代碼嗎?另外,作爲一個附註,你的'DataCommon'類應該實現'IDisposable',因爲你同時擁有一個'SqlCommand'和'SqlConnection'應該被丟棄。 – pstrjds

+0

根據錯誤消息,在'reader.Read()'發生異常的可能性更大。但是棧跟蹤似乎與另一種方法('GetEligibilityClass')相比,這裏顯示的方法('GetRequiredPercent')。 –

回答

-1

我對此有缺口...「CommandBehavior.CloseConnection」將關閉第一個完成的線程上的連接(這解釋了不一致性)。 嘗試刪除並刪除關閉「catch」中的連接(僅用於測試)。

相關問題