2013-05-02 168 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