TransactionScope中的NLog导致Transaction无效

时间:2012-05-22 23:00:15

标签: c# .net transactionscope nlog

我在生产环境中遇到问题,我没有在本地出现。

我在TransactionScope中运行一些LINQ to SQL代码,如下所示:

        using (var scope = new TransactionScope())
        {
            uploadRepository.SubmitChanges();
            result = SubmitFileResult.Succeed();

            ScanForNewData(upload);

            scope.Complete();
        }

ScanForNewData()调用GetSubmittedData()。如果GetSubmitted()中发生异常,我们使用Nlog将错误写入文件,数据库并发送电子邮件:

        catch (Exception ex)
        {
            //MT - having to comment this out beause it is causing a problem with transactions on theproduction server
            logger.ErrorException(String.Format("Error reading txt file {0} into correct format", upload.DocumentStore.FileName), ex);
            return new UploadGetSubmittedDataResult { Exception = ex, Success = false, Message = String.Format("Error reading txt file {0} into correct format", upload.DocumentStore.FileName) };
        }

在ScanForNewData中,我们然后调用repository.SubmitChanges()。这会导致:

该操作对交易状态无效。 System.Transactions.TransactionException TransactionException System.Transactions.TransactionException:该操作对事务的状态无效。

我提出的最好的想法是,在生产中,此代码在Web服务器上运行并调用单独的数据库服务器。 DataContext和Nlog都具有相同的连接字符串配置和Sql用户,但可能因为服务器是远程的(而本地我使用的是集成安全性)会发生奇怪的事情。

知道在这种情况下交易会发生什么?

更新 - 我刚刚在本地尝试了SQL用户,它仍然可以正常工作。必须与生产设置有关...

另一个更新 - 我说谎。在开发过程中,永远不会写入Nlog数据库记录,发送电子邮件,并且不会发生TransactionException。

3 个答案:

答案 0 :(得分:0)

如果没有异常的完整堆栈跟踪,很难猜出是什么问题,它可能取决于多种因素。

例如,我假设NLog打开了一个与我自己的db的新连接,这可能会导致事务被提升为分布式事务,并且分布式事务协调器将启动。这可能导致生产中的应用程序与本地行为之间的不对称。

您可能会通过其中的某些操作来破坏事务,例如某些未处理的异常或非法访问某些数据。

提供完整的堆栈跟踪和更多代码,以进行更深入的分析。

答案 1 :(得分:0)

如果不知道TransactionException的内部异常是什么,将难以解决,但这是一个想法:

如果您重构代码以便之后发生日志记录,那么事务范围周围的使用块已经结束,您可能会避免因为事务范围将结束而DTC将滚动而出现的问题支持交易。

我在过去使用过并看到过这种模式(在事务结束并回滚之后才记录)处理事务并且运行良好。

始终建议在单独的数据库上进行日志记录以避免此类问题。如果你这样做也会避免这个问题。

答案 2 :(得分:0)

看看这个......似乎是Nlog的一个错误。

https://groups.google.com/forum/#!msg/nlog-users/I5UR-bISlTA/6RPtOZhR4NoJ

建议的解决方案是使用异步目标进行Db日志记录。