2013-05-02 52 views
0

我試圖解決的問題如下:C#在循環嵌套事務,但回滾,如果其中任何失敗

我有一個從文件中攝取的數據並插入多個某些事情的過程表,因爲它現在全部用一個事務完成,但是,對於非常大的數據集,回滾或提交超時並失敗,無論我設置了什麼時間(至少就我所有的嘗試顯示的內容而言)我)。所以決定我需要重寫功能來「完成」任務。由於它目前是指當前代碼的僞代碼看起來像(使用,以避免不必要的信息僞代碼)

variable = FunctionThatReadsFromAFile(); 

ITransactionManager transactionObject = new TransactionManager(); 
IDbTransaction dbTransaction = transactionObject.Get(); 

WriteToFirstTable(variable ,dbTransaction); 
WriteToSecondtable(variable ,dbTransaction); 
WriteToThirdTable(variable ,dbTransaction); 

if(!Error) 
transactionObject.Commit(dbTransaction); 
else 
transactionObject.Rollback(dbTransaction); 

就像我說的,這個工作正常較小的數據集,但比當文件還有更多特定數量的行(取決於超時),它在提交或回滾時失敗。

例如,我不能只是將時間更改爲10,000秒,實際上由於程序的結構方式,我無法爲了測試目的而更改超時時間。所以我想要做的是讓程序一次處理100行,而不是一次完成整個文件,提交它們,但如果其中一組「一百個」失敗,則回滾一切,我已經理解了這可以通過嵌套事務來完成,但是這樣做;

using (TransactionScope outterTransaction = new TransactionScope()) 
{ 

    while(file.read()) 
    { 

     using (TransactionScope innerTransaction = new TransactionScope()) 

     { 

     variable = GetNextHundredOrLessRows(file); //100 rows at a time basically 

     WriteToFirstTable(variable ,innerTransaction); 

     WriteToSecondtable(variable ,innerTransaction); 

     WriteToThirdTable(variable ,innerTransaction); 


     if(!Error) 
     innerTransaction.Complete(); 
     else 
     innerTransaction.Rollback(); 

     } 

    } 

    if(!Error) 
     outterTransaction.Complete(); 
     else 
     outterTransaction.Rollback(); 

} 

不工作,任何想法我做錯了什麼?

非常感謝大家花時間試圖幫助我。

編輯:這是正確的軌道來解決這個問題?我讀過嵌套事務加入外部事務的範圍,所以我仍然遇到.Complete中的同一問題?

回答

0

我相信你需要在循環底部提交事務(這會導致你需要考慮的其他問題,即如何回滾)。如果你等到內部事務循環之外,所有事務將立即被捆綁並提交,這意味着性能實際上會比第一個例子的性能差得多。

編輯:如上所述,這會導致一個問題,如果一組插入失敗,您不能回滾更改。爲了解決這個問題,我認爲最簡單的解決方案是創建一個「RollBackStack」。在while循環中,您可以用一些必要的數據來推動某個對象,以便回滾到堆棧。您添加一個標誌來指示是否失敗。如果出現故障,則切換標誌並從循環中斷開。然後你彈出堆棧撤消更改,直到堆棧爲空。然後,您知道數據庫處於啓動之前的狀態。之後,您可以重試來自組1的插入。或者,您可以添加重試邏輯以從組x繼續,其中x是進行任何回滾之前失敗的組。如果在經過一定次數的重試後,您無法完成完整的插入,則進入回滾方法,直到彈出堆棧爲止。

+0

你好,謝謝你的回覆。 嗯,是的,我明白你的表現是什麼意思,但只要它真正做到我需要做的事情,我就可以犧牲表現。 如果我在循環底部提交事務,那麼如果在某一時刻其中一個集合失敗,那麼其餘的仍然會通過,這是我想要避免的。我需要他們全部進入,只要他們沒有失敗。 – 2013-05-02 16:37:37

+0

@ A.D我意識到這一點,並有一些解決方案。然而,性能是妨礙示例1運行的原因,因此,如果您嘗試在內部循環之外提交,則示例2永遠不會工作。我將編輯一個關於回滾的概念,它不完全漂亮,但它在邏輯上是合理的。 – evanmcdonnal 2013-05-02 17:08:58

+0

我會等待您的回覆,非常感謝! – 2013-05-02 17:32:52