DanAbdn
DanAbdn

Reputation: 7495

Async Await on MVC Controller with repository that selects and returns a collection

I have an MVC controller action that lists all of the "features" I have for a given "application" and then displays it as a table.

Am I using async correctly here?

The controller action is async i.e.

public async Task<IActionResult> List(string id)
{
  return View(await new FeatureRepository(_context).GetAllFeatures());
}

and my features repository (I'll instantiate via dependency injection later)...

public class FeatureRepository
{
  private ApplicationDbContext _context;

  public FeatureRepository(ApplicationDbContext context)
  {
    _context = context;
  }

  public async Task<IQueryable<ApplicationFeature>> GetAllFeatures()
  {
    var query = from d in _context.ApplicationFeatures
                select d;

    return query;
   }

}

Or do I need to use:

await query.ToListAsync()

Then return a List? Trying to avoid ToList of any kind as I don't want to run the query until it is required i.e. defer the execution.

It seems to run fine but before I reproduce this X times, I wanted to be sure it has been done in a way that does not still behave synchronously.

Thanks! Dan.

(MVC 6, ASP.NET 5, Entity Framework 7, VS2015)

Upvotes: 1

Views: 2108

Answers (1)

tede24
tede24

Reputation: 2354

Your await GetAllFeatures isn't awaiting nothing as the method isn't performing any async operation, just returning an IQueryable.

So you need to call ToListAsync somewhere. If you want your repo to return the queryable then remove all async/await from there and use the ToListAsync in the action.

By the way, remember naming async methods with Async suffix as suggested by Microsoft by convention.

Just for clarifying when EF exposes async and when not (because doesn't have any sense):

The point of async actions in MVC is to free IIS threads when there are operations not requiring IIS processing. The most common and clear case is DB operations. That's why mostly all MVC async examples are related to EF, because the you can leave IIS attend other requests meanwhile DB is processing queries.

That being said, and talking about EF, only EF methods that expose async are those that perform database operations. That's why you don't have "AddAsync" (because Add works only with DbContext) and you do have "SaveChangesAsync" (because it actually executes db insert in this case).

Conclusion: to take full advantage of async actions, you should use all EF async methods you have available. If your action doesn't consume any async method, then the action shouldn't be async.

Upvotes: 4

Related Questions