2013-05-08 206 views
2

我有一個插入方法可以在較小的數據集上正常工作,但一旦數據集超出特定大小,方法就會超時,而不管我在初始事務範圍中設置了什麼。C#中的TransactionScope中發生超時的問題

在代碼中使用簡單的存儲SQL過程插入的方法是所謂用「的ExecuteNonQuery」

我的代碼看起來是這樣的(絨毛去除):

 public void method() 
    { 

    using (TransactionScope testScope = new TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(1, 25, 0))) 
        { 

        timeDB.insert(var.time); 

        codeDB.insert(var.code); 

        foreach (variable var in listOfVariables) 
          { 

          nameDB.insert(var.value); 

          } 

        testScope.Complete(); 
        } 
    } 

我認爲這個問題有什麼使用命令超時而不是超時範圍,因爲代碼適用於較小的數據集......如果是這種情況,有什麼方法可以在不修改machine.config(或任何其他.config文件,我嚴格禁止修改它們,因爲更改值會使程序的其餘部分變得糟糕)

如果問題不是特定的命令超時,是什麼原因造成的?就像我說的那樣,代碼可以在8000-15000個插入之間的任何位置上正常工作(取決於我們的ConnectionString中設置的超時值「我們的程序配置文件中設置的連接超時值,我只能修改測試用途但不能更改任何值),但什麼比這更大,它崩潰。

此外,我敢肯定,這絕對不是範圍的超時值作爲任務timesout約幾分鐘後,沒有在附近的1小時25分鐘的TransactionScope的設置

預先感謝您花時間幫我解決此問題。

編輯:

通過請求,我添加了一個最終由nameDB.insert方法調用的插入方法的例子(刪除了Fluff,注意實際的插入方法實際上是NameDB.insert方法的子方法,而實際循環在nameDB.insert方法中。我只是使用NameDB ....等來減少絨毛。 )

public Int32 Insert(Hashtable serData, DataDO data) 
     { 
      int numAffected = 0; 

      IDataParameter[] parameters = 
        {      
         this.Helper.GetParameter("@Text", data.Text), 
         this.Helper.GetParameter("@CreationDt", ((data.CreationDate == DateTime.MinValue) 
         ? Convert.DBNull : data.CreationDate)),      
         this.Helper.GetParameter("@TypeId", data.TypeId),      
         this.Helper.GetParameter("@KeyId", DbType.Int32, 4, ParameterDirection.Output) 
        }; 

      numAffected = this.Helper.ExecuteNonQuery(this.ConnectionString, "InsertData", parameters); 

      if (numAffected > 0) 
       return Convert.ToInt32(parameters[parameters.Length - 1].Value); 

      return 0; 
     } 
+0

作爲瓦娜說,你想要的DbCommand對象的CommandTimeout屬性。你能提供更多關於你的例子中的timeDB和codeDB的信息嗎? – AFischbein 2013-05-08 19:58:21

+0

如果您的交易要轉入DTC,請注意DTC的最大超時時間非常短 - 出於一個非常好的理由:您不應該持有非常長時間的交易 - 尤其是「可序列化」的交易。 – 2013-05-08 20:04:29

+0

我已經編輯了帖子以添加插入方法,因爲它的評論太長了。感謝您的幫助。 – 2013-05-08 20:04:38

回答

0

我想你可以在代碼中設置命令超時:DBCommand,如果你使用的是命令。而DbCommand不會從事務範圍或連接字符串繼承,因此您必須手動進行設置。

+0

我會試試。謝謝! – 2013-05-16 15:35:32

0

交易不應該長時間運行! 這是在SQL Server等基礎平臺中設計的。超時就像安全閥;打開它們可能會導致系統崩潰。

Inserts花費這麼多時間的原因是因爲您爲每一行執行查詢。這意味着每行:

  1. 客戶有權將命令發送到SQL服務器
  2. SQL Server執行它
  3. SQL Server中的結果返回給客戶端

如果SQL連接在網絡上,每個迴路的延遲時間更長。

推薦的解決方案是批量發送插頁。有很多方法可以做到這一點,根據您可以投入重構的時間量,可以使用簡單的動態SQL字符串構建器SQLBulkLoad,也可以使用實體框架(Object Framework,EF)等對象關係映射(Object Relational Mapping,ORM)或支持批量更新的nHibernate。

使用ORM,您的代碼會改變這樣的事情:

public void method() 
{ 
    using(MyDatabase db = new MyDatabase()) 
    { 
     timeDB.insert(var.time); 
     codeDB.insert(var.code); 

     foreach (variable var in listOfVariables) 
     { 
      nameDB.insert(var.value); 
     } 

     using (TransactionScope testScope = new TransactionScope()) 
     { 
       db.SaveChanges(); 
       testScope.Complete();  
     } 
    } 
} 
+0

你好邁克爾, 謝謝你的迴應。我嘗試了你的建議,但仍然超時。如果我找到任何東西,會讓你知道。 謝謝! – 2013-05-16 15:36:29

+0

創建SQL腳本,將它們包裝在一個大事務中,並直接在SQL查詢分析器(或您正在使用的數據庫的相應工具)中運行它。它是否仍然超時?如果不是,需要多長時間才能完成? – Michael 2013-05-18 18:28:00