在C#中的TransactionScope中尝试/捕获

时间:2013-07-22 10:39:52

标签: c# asp.net transactionscope

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

我的代码示例:

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();
    }
}

1 个答案:

答案 0 :(得分:3)

首先,我发现代码示例的结构非常混乱。使用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 来改进您的设计。

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