I'm implementing a Model using EF 6.1.3 and .NET Framework 4.6.1. This model is used by an ASPNET app and by an ASPNET CORE app, for that reason it uses System.Data.Entity and it is located in a separate assembly mymodel.dll.
This is the model
using System.Data.Entity;
public partial class MyDbContext : DbContext
{
public virtual DbSet<Athlete> Athletes{ get; set; }
}
public partial class Athlete
{
public Athlete()
{
}
//...
public string Country { get; set; }
}
I'm developing the MVC app that is implemented in aspnet core with .NET Framework 4.6. It references EF 6.1.3 so that the model can be used.
public class MyViewModel
{
public IList<Athlete> ItalianAthletes{ get; set; }
}
using Microsoft.EntityFrameworkCore;
//solution: comment the previous line and use instead System.Data.Entity;
public class MyController : Controller
{
private readonly MyDbContext _context;
//...
public IActionResult Index()
{
MyViewModel myvm = new MyViewModel();
var result = _context.Athletes.Where(a=>a.Country=="Italy").ToList();
myvm.ItalianAthletes = result ;
return View(myvm);
}
}
... and it works as expected.
Now changing the Index method to async
public async Task<IActionResult> Index()
{
MyViewModel myvm = new MyViewModel();
var result = _context.Athletes.Where(a=>a.Country=="Italy").ToListAsync();
await result; //at this point an exception is thrown
//...
}
InvalidOperationException: The source IQueryable doesn't implement IAsyncEnumerable. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.
Removing the Where() clause the problem persists, so the problem seems related to ToListAsync();
var result = _context.Users.ToListAsync();
Carefully reading the text of the exception I understand that "the IQueryable generated by ToList() doesnt implement IAsyncEnumerable " but this doesnt make sense to me because all that behavior is internal to ToListAsync();
Someone can help me to better understand what's happening here under the hood? and what can I do so that ToListAsync() works as expected ?
thank you in advance for any comment
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:
This topic is old but I ran into the same error in the year 2021 for same or different reasons.
In short: Get rid of .ToListAsync()
and replace it with .ToList()
I ran into this issue in my .NET5 project by using EntityFrameworkCoreMock.Moq in a unit test project and failed with this error. I asked a friend and was told to get rid of ToListAsync(). I decided to also get rid of AsyncFixer for that reason.
I'm not really happy with that solution either and hate code that fails at runtime for strange reasons in general. But that's the solution I ended up with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With