998*_*823 2 c# asynchronous entity-framework async-await asp.net-web-api
我有一个Web API方法,可以获得仪表板视图.
该方法调用大约24个不同的查询.每个查询执行大约需要60ms,我正在使用Glimpse进行配置.
我希望这样做,是异步运行它们,以避免一个接一个地调用每一个,从而使它成为60ms X 5方法调用.
我也是Async Await的新手,所以我的期望可能不正确.
这是我的Web API方法
[HttpGet]
[ExceptionHandling]
public async Task<DashboardResponse> GetDashboard()
{
return await DashboardResponse.GetDashboard();
}
Run Code Online (Sandbox Code Playgroud)
这是辅助方法
public static async Task<DashboardResponse> GetDashboard()
{
var resp = new DashboardResponse();
resp.MonthGlance = await GetMonthAtAGlance();
resp.MostRecentOrder = await GetMostRecentOrder();
resp.CreateAnOrder = await GetCreateAnOrder();
resp.RecentOrders = await GetRecentOrders();
resp.RecentNotifications = await GetRecentNotifications();
var messages = MessageResponse.GetMessages(new MessageFilters() { PageNumber = 1, PageSize = 10 }).Messages;
resp.RecentMessages.Messages = messages;
resp.OrderLineChart = GetOrderLineChart();
return resp;
}
Run Code Online (Sandbox Code Playgroud)
这是辅助方法内部调用的方法之一(其余方法设置非常相似)
public static async Task<MonthGlanceResp> GetMonthAtAGlance()
{
var monthAtAGlance = new MonthGlanceResp();
var monthStart = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
var monthEnd = monthStart.AddMonths(1).AddDays(-1);
var monthGlanceQuery = Helpers.DbContext.Current.Orders
.Where(c => c.Status != OrderStatuses.Deleted &&
(c.OrderSubSource == OrderSubSources.ApplicantLink ||
c.OrderSubSource == OrderSubSources.BulkImport ||
c.OrderSubSource == OrderSubSources.OrderComprehensive) &&
c.DateIn >= monthStart &&
c.DateIn <= monthEnd).AsQueryable();
if (UserContext.Current.AccountAccess == CustomerAccessTypes.Global)
{
monthGlanceQuery = monthGlanceQuery.Where(c => c.CustomerId == UserContext.Current.CustomerId);
}
else if (UserContext.Current.AccountAccess == CustomerAccessTypes.Account)
{
monthGlanceQuery = monthGlanceQuery.Where(c => c.CustomerAccountId == UserContext.Current.CustomerAccountId);
}
else
{
monthGlanceQuery = monthGlanceQuery.Where(c => c.CustomerAccountPersonId == UserContext.Current.CustomerAccountPersonId);
}
monthAtAGlance.ClearOrderCount = await monthGlanceQuery
.CountAsync(c => c.OrderLineItems
.Where(d => d.ItemType == "package_service" || d.ItemType == "service")
.All(d => d.Result == OrderLineItemResults.Clear && d.Status == OrderLineItemStatuses.ApprovedForClient));
monthAtAGlance.QuestionableOrderCount = await monthGlanceQuery
.CountAsync(c => c.OrderLineItems
.Where(d => d.ItemType == "package_service" || d.ItemType == "service")
.All(d => d.Status == OrderLineItemStatuses.ApprovedForClient) &&
c.OrderLineItems
.Where(d => d.ItemType == "package_service" || d.ItemType == "service")
.Any(d => d.Result == OrderLineItemResults.Questionable));
monthAtAGlance.PendingOrderCount = await monthGlanceQuery
.CountAsync(c => c.OrderLineItems
.Where(d => d.ItemType == "package_service" || d.ItemType == "service")
.Any(d => d.Status != OrderLineItemStatuses.ApprovedForClient));
monthAtAGlance.OrderCount = await monthGlanceQuery.CountAsync();
return monthAtAGlance;
}
Run Code Online (Sandbox Code Playgroud)
唯一的问题是,在实现所有异步等待更改后,似乎web api调用现在比以前运行得慢!我不确定我是否有正确的结构,或者即使我正在考虑的是可能的.
唯一的问题是,在实现所有异步等待更改后,似乎web api调用现在比以前运行得慢!
除非引入并发,否则异步代码的运行速度比同步代码慢.
旁注:异步代码通常用在服务器应用程序(例如,ASP.NET)上,即使单个请求没有并发性,因为即使每个单独的请求(稍微)较慢,整个系统也可以进一步扩展.
所以,你需要并发.
不同的查询
你可能想要考虑一下.如果您正在使用SQL Server的单个实例,那么您是否真的可以从同时执行查询中获得任何好处?也许,也许不是.最好先测试一下.
请注意,实体框架 - 虽然它允许异步查询 - 但每个上下文一次只允许一个异步查询.您需要为每个并发查询创建不同的上下文.所以你需要小心并发查询,因为你的一些实体来自不同的上下文.
也就是说,您可以执行如下所示的并发调用:
public static async Task<DashboardResponse> GetDashboardAsync()
{
var resp = new DashboardResponse();
var monthAtAGlanceTask = GetMonthAtAGlanceAsync();
var mostRecentOrderTask = GetMostRecentOrderAsync();
...
await Task.WhenAll(monthAtAGlanceTask, mostRecentOrderTask, ...);
resp.MonthGlance = await monthAtAGlanceTask;
resp.MostRecentOrder = await mostRecentOrderTask;
...
return resp;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您的代码几乎肯定无法使用Helpers.DbContext.Current; 每个并发查询都需要自己的上下文.
| 归档时间: |
|
| 查看次数: |
617 次 |
| 最近记录: |