我在生产环境中遇到问题,我没有在本地出现。
我在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。
答案 0 :(得分:0)
如果没有异常的完整堆栈跟踪,很难猜出是什么问题,它可能取决于多种因素。
例如,我假设NLog打开了一个与我自己的db的新连接,这可能会导致事务被提升为分布式事务,并且分布式事务协调器将启动。这可能导致生产中的应用程序与本地行为之间的不对称。
您可能会通过其中的某些操作来破坏事务,例如某些未处理的异常或非法访问某些数据。
提供完整的堆栈跟踪和更多代码,以进行更深入的分析。
答案 1 :(得分:0)
如果不知道TransactionException的内部异常是什么,将难以解决,但这是一个想法:
如果您重构代码以便在之后发生日志记录,那么事务范围周围的使用块已经结束,您可能会避免因为事务范围将结束而DTC将滚动而出现的问题支持交易。
我在过去使用过并看到过这种模式(在事务结束并回滚之后才记录)处理事务并且运行良好。
始终建议在单独的数据库上进行日志记录以避免此类问题。如果你这样做也会避免这个问题。
答案 2 :(得分:0)
看看这个......似乎是Nlog的一个错误。
https://groups.google.com/forum/#!msg/nlog-users/I5UR-bISlTA/6RPtOZhR4NoJ
建议的解决方案是使用异步目标进行Db日志记录。