Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations

If you are using Entity Framework Core then you have to use this namespace:

using Microsoft.EntityFrameworkCore;

instead of

using System.Data.Entity;

You will want to do one of these 2 things.

Reference the EF nuget package in both assemblies. This is because this ToListAsync() operation is actually being called through to your EF DbContext and this cannot be done from a project that has no reference to the EF NugetPackage. If this is already the case make sure you are referencing the namespace System.Data.Entity in the using statements at the top of the code:

using System.Data.Entity;

as this is the location of the extension method ToListAsync you want to call.


Wrap the code that retrieves from EF in a service in your project that uses EF, make the call async, and call that from your asp.net mvc project. This would be my preferred choice as it adds a nice layer of abstraction and makes your code easier to test/maintain.

Code example for 2nd option

public interface IAthleteService {
    Task<List<Athlete>> GetAthletesByCountryAsync(string country, CancellationToken token);
}

public class AthleteService : IAthleteService {
    private MyDbContext _context;
    public async Task<List<Athlete>> GetAthletesByCountryAsync(string country, CancellationToken token)
    {
        return await _context.Athletes.Where(athlete => athlete.Country == country).ToListAsync(token).ConfigureAwait(false);
    }
}

public class MyController : Controller
{
    private readonly IAthleteService _service;
    //...
    public async Task<IActionResult> Index(CancellationToken token)
    {
       MyViewModel myvm = new MyViewModel();
       myvm.ItalianAthletes = await _service.GetAthletesByCountryAsync("Italy", token).ConfigureAwait(true);
       // rest of code
    }   
}

Notes:

  • I used a CancellationToken, it allows for the cancellation of an async operation. This is completely optional.
  • I used ConfigureAwait, this allows you to specify whethere the same thread context should be recaptured when the operation resumes. It saves resources to not do it (pass false) but you can only do that when its possible. In the above example its done in the library. Also in the example above it is not done from the Controller because you need the Http context associated with the thread (pass true).
  • I did not take into account cleaning up of resources (like making AthleteService disposable to cleanup the DbContext) or any injection of dependencies.