不要在Entity Framework中出错时回滚事务

3
当实体框架操作出现错误时,任何环境事务都会被中止,并且我无法将其用于更多的数据库工作。例如,当我尝试打开嵌套的事务范围时,它会抛出一个TransactionAbortedException异常,显示“事务已中止”。
如果我预计会出现错误并知道如何继续,我该怎么办?
using (var scope = new TransactionScope())
{
    using (var ctx = new MyContext())
    {
        try
        {
            var x = ctx.MyEntities.FirstOrDefault();
        }
        catch
        {
            CreateTable();
            // Custom DDL command. I can't use EF migrations.
            // Should that fail or not help, I'm happy to see more exceptions later.
        }
        // TODO: Transaction scope is already aborted!
        ctx.MyEntities.Add(...);
    }
    scope.Complete();
}

如果有帮助的话,我可以创建一个新的DbContext实例。
1个回答

1
SQL Server没有记录哪些异常会回滚事务。你不能阻止它回滚,这实在很愚蠢,也没有技术上的理由。此外,如果出现错误,它很容易继续执行(然后没有事务)。而且,哪些错误会回滚,哪些不会回滚是相当不可预测的。
EF没有回滚事务。这是SQL Server做的。
您可能可以使用异常处理执行原始SQL:
TRY
 YourStatementHere
END TRY
CATCH
...

这个HTML代码的翻译是:“

这个 应该 保持交易活着。


我正在使用映射查询的Entity Framework。此外,这应该适用于多个数据库。(事实上,我首先是在测试SQL Server,但我没有提到它。)这里不允许使用大量定制的SQL。在这种情况下,预计会出现“表不存在”的错误,因此采取CreateTable调用作为处理错误的措施。另外,需要注意的是,数据库服务器已经中止了事务,而不是EF。 - ygoe
1
那么你就没那么幸运了...也许你可以启动一个不同的连接+事务对,在那里进行检查。你的主要事务将会继续存在。 - usr
就是这样,使用选项Suppress的另一个TransactionScope解决了问题。我需要将可能失败的命令从事务中取出。由于它可能返回过时的数据,如果没有错误,我必须在事务内重复执行它并使用该结果。 - ygoe
OK。另一个警告:EF为每个查询打开一个新连接。这会导致升级到MSDTC。在您的计算机上禁用MSDTC以解决此类问题。 - usr
我没有观察到任何与分布式事务相关的问题,即使 MSDTC 服务停止了。只使用单个数据库。此外,关于 SQL Server,从我所读的内容来看,这个问题应该在 7 年前的 SQL Server 2008 中得到解决。 - ygoe
我不确定您指的修复措施是什么。如果您恰好两次从池中取出相同的物理连接,则即使您使用多个连接,也可能不会发生MSDTC升级。这是一种隐匿的问题。通常,在测试期间您不会注意到它。在生产环境下,承受负载时可能会发生此问题。 - usr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接