如何针对不同的上下文使用事务?

How to use transactions for different contexts?

在我的应用程序中,我的方法如下所示:

public static bool DoLargeOperation()
{
    bool res = true;

    res = res && DoFirstSubOperation();
    res = res && DoSecondSubOperation();
    res = res && DoThirdSubOperation();

    return res;
}

每个内部方法如下所示:

public static bool DoFirstSubOperation()
{
    using (var context = new EntityFrameworkContext())
    {
        // data modification.
        context.SaveChanges();
    }
}

例如,DoFirstSubOperation()DoSecondSubOperation() 成功完成,但 DoThirdSubOperation() 失败。 如何回滚前两个函数所做的更改?

这种方法没有带来结果:

using (var transaction = new TransactionScope())
{
    res = res && DoFirstSubOperation();
    res = res && DoSecondSubOperation();
    res = res && DoThirdSubOperation();
}

我看到的唯一解决方案是像这样定义上下文:

public static bool DoLargeOperation()
{
    bool res = true;

    using (var context = new EntityFrameworkContext())
    {
        using (var transaction = context.Database.BeginTransaction())
        {

            res = res && DoFirstSubOperation(context);
            res = res && DoSecondSubOperation(context);
            res = res && DoThirdSubOperation(context);
            if (res)
            {
                transaction.Commit();
            }
            else
            {
                transaction.Rollback();
            }
        }
    }

    return res;
}

但是这样做可以接受吗?或者有其他解决方案吗?

是的,这是正确的模式。将上下文传递到方法中允许在多个位置重用方法,因为上下文和事务将由调用者管理。

尽管如此,您可能希望在第一个方法失败后停止处理后续方法。您还可能希望将对子项的调用包装在 try/catch 中,以便任何异常都允许回滚正确发生...

try
{
    res = DoFirstSubOperation(context);
    if (res) 
        res = DoSecondSubOperation(context);
    if (res) 
        res = DoThirdSubOperation(context);    

    if (res)
        transaction.Commit();
    else
        transaction.Rollback();
}
catch
{
    transaction.Rollback();
}

如果您的子方法已经处理了异常,那么您可以放弃 try/catch。