1

我在我的 c# 代码中使用事务。在 TransactionScope 中,我记录了几乎所有内容,以确保所有内容都在测试中完成。但是,如果事务中发生了某些事情并且它去捕获我的日志类不会写任何东西。在 localhost 我将 TransactionScopeOption 更改为“ Suppress ”,因为数据库不在我的服务器中。当我调试一切正常时,我可以写入日志文件。但是当我更改为“必需”时,如果它给出错误,它会像往常一样取消所有内容,但它也无法写入第一个日志。我怎样才能解决这个问题?

我的代码示例:

TransactionOptions tr = new TransactionOptions();
tr.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, tr, System.Transactions.EnterpriseServicesInteropOption.Automatic))//System.TimeSpan.MaxValue))
{
    bool status = false;
    // this log must be written anyway but it won't when it gives an error.
    LogProcess log = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction begun.");
    try
    {
        // process 1
        // process 2
        .
        .
        .
        if(status)
        {
            LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction will complete soon.");
            scope.Complete();
            LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction completed.");
        }
        else
        {
            LogProcess log2 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction will dispose.");
            scope.Dispose();
            LogProcess log2 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction disposed.");
        }

    }
    catch(Exception ex)
    {
        LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction exception. Error: " + ex.Message);
        scope.Dispose();
    }
}
4

1 回答 1

4

首先,我发现您的代码示例的结构非常混乱。使用 TransactionScope 时,通常不会在调用 scope.Complete() 或 scope.Dispose() 之后编写语句。此外, using 语句为您处理范围,因此恕我直言,如果您能提供帮助,您不应显式调用 scope.Dispose()。换句话说:尝试重构您的代码,使其看起来像这样:

private void PerformTransactionalOperation()
{
    Log.Write("Starting operation.");        

    try
    {
        using (var scope = CreateTransactionScope())
        {
            if (PerformTransactionalOperationCore())
            {
                Log.Write("Committing...");
                scope.Complete();
                Log.Write("Committed");
            }
            else
            {
                Log.Write("Operation aborted.");
            }
        }
    }
    catch (Exception exception)
    {
        Log.Write("Operation failed: " + exception.Message);
        throw;
    }
}

private bool PerformTransactionalOperationCore()
{
    // Perform operations and return status...
}

其次,事务范围专门设计为仅在没有引发异常时完成,因此可以通过让 PerformTransactionalOperationCore 抛出特定异常而不是返回false来改进您的设计。

然后关于日志记录问题:确保您的日志记录框架不参与与您正在记录的操作相同的事务。您可以通过始终使用选项Suppress在 TransactionScope 中登录来做到这一点(即,当您首先登录到事务感知的资源时,例如数据库)。顺便说一句,你为什么要通过实例化新的 LogProcess 实例来编写日志语句?

于 2013-07-22T11:18:15.540 回答