在TransactionScope中使用NLog会导致事务无效

3

我在生产环境中遇到了一个问题,但在本地测试环境中没有出现过。

我正在使用如下代码在TransactionScope中运行一些LINQ to SQL代码:

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

            ScanForNewData(upload);

            scope.Complete();
        }

ScanForNewData() 调用 GetSubmittedData()。如果在 GetSubmittedData() 中出现异常,我们使用 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没有发生。

在什么情况下,一个SQL连接会自动加入到环境事务中? - Joe
3个回答

0

0

没有完整的异常堆栈跟踪很难猜测问题所在,可能涉及多个因素。

例如,我假设NLog会自己打开一个新连接到数据库,这可能会导致事务升级为分布式事务,并触发分布式事务协调器。这可能会导致您的应用程序在生产环境和本地环境中行为不对称。

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

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


0

不知道TransactionException的内部异常是什么,很难解决,但是有一个想法:

如果您重构代码,使日志记录发生在事务范围周围的using块结束之后,您可能会避免您遇到的问题,因为事务范围将被结束,DTC将回滚事务。

我过去使用并看到过这种模式(在事务结束和回滚之后才记录日志),在处理事务时效果很好。

始终建议在单独的数据库上执行日志记录,以避免出现此类问题。如果您这样做,问题也将得到解决。


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