.net - C# 事务中的事务

标签 .net sql-server transactions

我正在使用 C# 将发票平面文件导入到数据库中。如果遇到问题,我将使用 TransactionScope 回滚整个操作。

这是一个棘手的输入文件,因为一行不一定等于一条记录。它还包括链接记录。发票将包含标题行、行项目和总计行。有些发票需要跳过,但我可能不知道需要跳过,直到达到总行数。

一种策略是将标题、行项目和总行存储在内存中,并在达到总行后保存所有内容。我现在正在追求这个。

但是,我想知道是否可以用不同的方式来完成。围绕发票创建“嵌套”事务,插入标题行和行项目,然后在达到总行数时更新发票。如果确定需要跳过发票,则此“嵌套”事务将回滚,但整个事务将继续。

这可能、实用吗?您将如何设置?

最佳答案

TransactionScope 都不是SQL Server 也不支持嵌套事务。

你可以嵌套TransactionScope实例,但仅具有嵌套事务的外观。实际上,存在一种称为“环境”事务的东西,并且一次只能有一个。哪个事务是环境事务取决于您的用途 TransactionScopeOption当您创建范围时。

要更详细地解释,请考虑以下内容:

using (var outer = new TransactionScope())
{
    DoOuterWork();

    using (var inner1 = new TransactionScope(TransactionScopeOption.Suppress))
    {
        DoWork1();
        inner1.Complete();
    }

    using (var inner2 = new TransactionScope(TransactionScopeOption.RequiresNew))
    {
        DoWork2();
        inner2.Complete();
    }

    using (var inner3 = new TransactionScope(TransactionScopeOption.Required))
    {
        DoWork3();
        inner3.Complete();
    }

    outer.Complete();
}

以下是每个内部作用域发生的情况:

  • inner1在隐式事务中执行,独立于 outerDoWork1 中没有发生任何事情保证是原子的。如果中途失败,您将获得不一致的数据。此处发生的任何工作始终都会提交,无论 outer 发生什么情况。 .

  • inner2在新事务中执行,独立于 outer 。这是与 outer 不同的交易但它嵌套。如果失败,outer中发生的工作( DoOuterWork() ) 和任何其他范围仍然可以提交,但问题是:如果完成,则回滚整个 outer事务将不会回滚 inner2 内完成的工作. 这就是它不是真正嵌套的原因。另外,inner2将无权访问由 outer 锁定的任何行,所以如果你不小心,你可能会在这里陷入僵局。

  • inner3在与outer相同的交易中执行。这是默认行为。如果DoWork3()失败并且 inner3永远不会完成,那么整个outer事务被回滚。类似地,如果 inner3成功完成但 outer回滚,然后 DoWork3() 中完成的任何工作也被回滚。

所以你可以看到这些选项实际上都不是嵌套的,并且不会给你你想要的东西。 Required选项近似于嵌套事务,但无法让您独立提交或回滚事务内的特定工作单元。

在 SQL Server 中您可以获得的最接近真正嵌套事务的是 SAVE TRAN结合一些声明TRY/CATCH block 。如果您可以将逻辑放入一个或多个存储过程中,这将是一个不错的选择。

否则,您需要按照 Oded 的建议对每张发票使用单独的交易。

关于.net - C# 事务中的事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2794761/

相关文章:

c# - 在 PropertyGrids 中是否有更好的 StringCollection 编辑器?

.net - 具有动态模型的 Dapper ORM - 如何不返回任何字段而不是 'Field' = NULL?

python - 尝试将字符串插入 SQL Server 的问题

sql - 我需要游标来在 SQL 中完成这项工作吗?

PHP/MySQL - 散列到 BIGINT 以确保不重复

sql-server - 什么时候会释放 "nested transaction"中的 XLOCK?

c# - 在 Silverlight 中重新抛出异常时保留堆栈跟踪

.net - 如何使用 DateTime 指定一天中的最晚时间

sql - 为什么它给我 "Must declare the Scalar variable "@jobnumber""

php - PHP 的 mysql 扩展是否不支持 "FOR UPDATE"的事务?