我设置了一个Web API 2端点来测试2秒以上的 ADO.NET 调用。当试图"爆发"这个api,在使用异步方法时会失败。我的连接超时和读卡器超时。当"突发"时,这种方法的同步版本不会发生这种情况。真正的问题如下......
异步 ADO.NET 在抛出异常时表现得很奇怪。我可以看到Visual Studio输出中抛出的异常,但它们不会被我的代码捕获。正如您将在下面看到的那样,我尝试围绕几乎所有事情包装尝试/捕获并且没有结果。我这样做是为了能够设置断点。我知道抓住异常只是为了抛弃它们是不好的。最初,我只将调用包装在API层中。最糟糕的是,这会锁定整个服务器。
显然,我对于async ADO.NET 缺少了一些东西。有什么想法吗?
编辑: 只是为了澄清我在这里要做的事情。这只是我本地计算机上的一些测试代码,它们与我们的开发数据库进行通信。这只是为了证明/反驳我们可以使用异步方法处理更多流量来对抗长时间运行的数据库调用。我认为正在发生的事情就是电话堆积起来。在这样做的过程中,等待连接和读者会超时,因为我们没有尽快回复它们。这就是为什么它在同步运行时不会失败的原因。这是一个完全不同的问题。我担心的是,操作不会以可捕获的方式抛出异常。以下不是生产代码:)
Web API2控制器:
[Route("api/async/books")]
[HttpGet]
public async Task<IHttpActionResult> GetBookAsync()
{
// database class instantiation removed
// search args instantiation removed
try
{
var books = await titleData.GetTitlesAsync(searchArgs);
return Ok(books);
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
数据访问:
public async Task<IEnumerable<Book>> GetTitlesAsync(SearchArgs args)
{
var procName = "myProc"
using(var connection = new SqlConnection(_myConnectionString))
using (var command = new SqlCommand(procName, connection) { CommandType = System.Data.CommandType.StoredProcedure, CommandTimeout = 90 })
{
// populating command parameters removed
var results = new List<Book>();
try
{
await connection.OpenAsync();
}
catch(Exception ex)
{
throw;
}
try
{
using (var reader = await command.ExecuteReaderAsync())
{
try
{
while (await reader.ReadAsync())
{
// FROM MSDN:
// http://blogs.msdn.com/b/adonet/archive/2012/07/15/using-sqldatareader-s-new-async-methods-in-net-4-5-beta-part-2-examples.aspx
// Since this is non-sequential mode,
// all columns should already be read in by ReadAsync
// Therefore we can access individual columns synchronously
var book = new Book
{
Id = (int)reader["ID"],
Title = reader.ValueOrDefault<string>("Title"),
Author = reader.ValueOrDefault<string>("Author"),
IsActive = (bool)reader["Item_Active"],
ImageUrl = GetBookImageUrl(reader.ValueOrDefault<string>("BookImage")),
ProductId = (int)reader["ProductID"],
IsExpired = (bool)reader["Expired_Item"]
};
results.Add(book);
}
}
catch(Exception ex)
{
throw;
}
}
}
catch(Exception ex)
{
throw;
}
return results;
}
}