ASP.NET MVC API与Web API异步

ahe*_*ick 0 c# asp.net-mvc entity-framework async-await asp.net-web-api

我目前正在使用ASP.NET MVC和单个Controller来获得各种"API".我正在使用从每个操作方法调用的服务/存储库模式.

类似如下:

库:

    public IQueryable<Order> GetOrders()
    {
        return from sqlOrder in DB.Orders
               select new Order
               {
                   Id = sqlOrder.Id,
                   Name = sqlOrder.Name,
                   Price = sqlOrder.Price
               };
    }
Run Code Online (Sandbox Code Playgroud)

服务:

    public List<Order> GetOrders()
    {
        return Repo.GetOrders().ToList();
    }
Run Code Online (Sandbox Code Playgroud)

控制器/行动:

    public JsonResult GetOrders()
    {
        var orders = Service.GetOrders();

        return Json(orders, JsonRequestBehavior.AllowGet);
    }
Run Code Online (Sandbox Code Playgroud)

一切都很好,但我正在考虑转移到WEB API和Async/Await

类似如下:

存储库:(无变化)

    public IQueryable<Order> GetOrders()
    {
        return from sqlOrder in DB.Orders
               select new Venue
               {
                   Id = sqlOrder.Id,
                   Name = sqlOrder.Name,
                   Price = sqlOrder.Price
               };
    }
Run Code Online (Sandbox Code Playgroud)

服务:

    public async Task<List<Order>> GetOrders()
    {
        return await Repo.GetOrders().ToListAsync();
    }
Run Code Online (Sandbox Code Playgroud)

控制器/行动:

    [ResponseType(typeof(List<Order>))]
    public async Task<IHttpActionResult> GetOrders()
    {
        var orders = await Service.GetOrders();

        return Ok(orders);
    }
Run Code Online (Sandbox Code Playgroud)

首先,这个async/await和Repository模式有什么问题吗?

使用原始MVC框架作为端点的"API"有什么重大缺点吗?而不是使用"Web API"?

Kri*_*tof 6

你已经回答了自己的问题:)

通过使用async/await,iis工作线程可以重用一个线程.假设您的api正在接收1000个呼叫/秒.如果您的线程限制设置为100,那么900个呼叫将等待空闲,直到请求完全结束.

但是,通过使用async/await,线程将更快地分配给900个等待请求,并且负载将更快地到达您的数据库(并且更难).

假设您的最大线程数为1,1个db持续10秒,而服务器可以在50ms内从webrequest启动数据库调用.
通过使用异步,您可以启动200 db调用(每50 ms 1次),如果不释放该线程则启动1.

至于你的第二个问题:大多数人不会在他们的控制器内部进行数据访问,但它是一个非常简洁易懂的例子.
如果我的项目足够简单(想想网格屏幕),我甚至更喜欢在控制器内使用EF语句而不是创建DAL层.
不要忘记EF本身就是一个存储库,它甚至还有一个工作单元...

编辑
将businessLogic从控制器中包装在一个单独的层中确实是一个好主意.
你可以使用服务并为你想要做的每个查询公开一个方法,但我一直在那条路上,我经常发现我的服务变得臃肿,因为开发人员根据自己的意愿制作了越来越多的方法.

最近我采用了命令查询系统.查询只返回数据,命令只执行某些操作.分离有助于保持代码清洁,开发人员更多地考虑创建一个全新的queryClass,就像他们创建一个方法时一样(即使影响是相同的).

我通常会使我的查询有点动态,但不会太多.
例如,OrderQuery可以包含2个构造函数,1个具有customerID,1个具有typeID),然后查询将应用更多的过滤器或更少的过滤器,具体取决于它的构造方式.
如果我需要说出销售价值超过X的所有最新订单,我可能会创建一个新的查询GetOrdersByValue.
通过这种方式,查询本身可以保持干净和专注(这会导致更快的速度,开发人员不会重新启动轮子,因为他们认识到他们的请求应该已经存在).