我们遇到了Entity Framework的一个奇怪问题。我们正在尝试向数据库添加一个新对象,并且正在从几个不同的位置执行此操作。两者都使用通过nuget包加载的以下代码:
public async Task<Guid> AddRecurrenceHistoryAsync(RecurrenceHistory recurrenceHistory, Guid recurrenceId)
{
_logger.DebugLogInformation("+");
try
{
using (RecurringPaymentsContext context = new RecurringPaymentsContext())
{
var recur = context.RecurringPayments.Single(r => r.Id == recurrenceId);
if (recur.RecurrenceHistories == null)
{
_logger.DebugLogInformation($"No existing histories found");
recur.RecurrenceHistories = new List<RecurrenceHistory>();
}
recur.RecurrenceHistories.Add(recurrenceHistory);
_logger.DebugLogInformation($"Saving Changes");
var result = await context.SaveChangesAsync();
_logger.DebugLogInformation($"Changes Saved result: {result}");
}
}
catch (Exception e)
{
_logger.DebugLogError(e.ToString());
throw;
}
_logger.DebugLogInformation(string.Format("- return: {0}", recurrenceHistory.Id));
return recurrenceHistory.Id;
}
在我们的控制台应用程序中执行此操作非常有效,但是我们也尝试从WebApi服务端点(下面给出的简化测试代码)执行此操作,并且从那里调用它时代码卡在var result = await context.SaveChangesAsync();
上线。
Web服务测试端点:
[HttpGet]
[Route("test")]
public HttpResponseMessage Test()
{
var paymentHistory = new RecurrenceHistory()
{
SystemId = Guid.NewGuid(),
TotalAmount = -1
};
_logger.DebugLogInformation("Adding recurrence history");
paymentHistory.Id = _recurrenceHistoryRepository.AddRecurrenceHistoryAsync(paymentHistory, Guid.Parse("3c412e1b-7a87-e711-910c-0050569b7221")).Result;
return Request.CreateResponse(true);
}
此测试端点尝试使用我们知道已在数据库中的Guid添加对象,现在仅用于测试目的,但在运行时,代码将进入上述var result = await context.SaveChangesAsync();
行,然后卡住。没有更多的记录,调试器停在那里,永远不会返回。不会抛出异常,但新行确实会添加到数据库中。
tl; dr摘要:
控制台应用程序可以成功调用此存储库方法来添加对象并可以继续,但是Web服务可以成功地将对象添加到数据库,但代码永远不会从context.SaveChangesAsync()
方法返回。
我们尝试过的事情:
将有问题的失败行更改为await Task.Run(() => context.SaveChangesAsync());
,尝试将工作流程添加到服务的应用池中,以及其他一些值得一提的事情。
答案 0 :(得分:6)
不要拨打.Result
,这是一个阻止呼叫,更重要的是,它会导致死锁。请改用await
,让控制器方法返回Task
。这实际上是异步/等待的101。有关详细说明,请参阅this。