Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#将事务嵌套在循环中,但如果其中任何一个失败,则回滚_C#_Sql Server_Transactions_Transactionscope_Rollback - Fatal编程技术网

C#将事务嵌套在循环中,但如果其中任何一个失败,则回滚

C#将事务嵌套在循环中,但如果其中任何一个失败,则回滚,c#,sql-server,transactions,transactionscope,rollback,C#,Sql Server,Transactions,Transactionscope,Rollback,我试图解决的问题如下: 我有一个从文件中摄取数据并在多个表中插入某些内容的流程,就像现在一样,所有这些都是通过一个事务完成的,但是对于非常大的数据集,回滚或提交超时会失败,无论我将超时设置为什么(至少我所有的尝试都显示了这一点)。所以决定我需要重写功能来“切碎”任务。当前代码的伪代码类似于(用于避免不必要信息的伪代码) 正如我所说,这对于较小的数据集很好,但是当文件的行数超过特定数量(取决于超时)时,提交或回滚失败 例如,我不能仅仅将超时更改为10000秒,事实上,由于程序的结构方式,我根本不能

我试图解决的问题如下:

我有一个从文件中摄取数据并在多个表中插入某些内容的流程,就像现在一样,所有这些都是通过一个事务完成的,但是对于非常大的数据集,回滚或提交超时会失败,无论我将超时设置为什么(至少我所有的尝试都显示了这一点)。所以决定我需要重写功能来“切碎”任务。当前代码的伪代码类似于(用于避免不必要信息的伪代码)

正如我所说,这对于较小的数据集很好,但是当文件的行数超过特定数量(取决于超时)时,提交或回滚失败

例如,我不能仅仅将超时更改为10000秒,事实上,由于程序的结构方式,我根本不能出于测试目的更改超时。所以我想做的是让程序一次处理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上遇到同样的问题吗

>我相信你需要把事务提交到循环的底部(这将导致你需要考虑的其他问题(即如何回滚)。如果等待到内部事务循环之外,所有事务都将被捆绑并立即提交,这意味着性能实际上要比第一个示例的性能差得多


编辑:如前所述,这会导致一个问题,即如果一组插入失败,则无法回滚更改。要解决这个问题,我认为最简单的解决方案是创建一个“回滚”。在while循环中,您使用回滚到堆栈上所需的任何数据将某个对象推送到堆栈上。您添加了一个标志,以指示某项操作是否失败。如果出现故障,则切换标志并中断循环。然后弹出堆栈撤消更改,直到堆栈为空。然后您就知道数据库处于启动前的状态。之后,您可以从组1重试插入。或者,您可以添加重试逻辑以从组x继续,其中x是执行任何回滚之前失败的组。如果经过一定次数的重试后,未能完成完整插入,则进入回滚方法,在该方法中弹出堆栈直到为空

你好,谢谢你的回复。是的,我明白你说的表演是什么意思,但我可以牺牲表演,只要它真的做了我需要的。如果我在循环的底部提交事务,那么如果在某个点上其中一个集合失败,那么其余的仍然会通过,这就是我想要避免的。我需要他们全部加入,除非他们都没有失败。@A.D我意识到这一点,并找到了解决办法。然而,性能是阻止示例1运行的原因,因此,如果您尝试在内部循环之外提交,那么示例2永远不会起作用。我将编辑一个如何回滚的想法,它并不完全漂亮,但逻辑上是合理的。
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();

}