So I have a context class EFCoreMContext with defined property EFCore.DBSet<AccessTime> AccessTime
public class EFCoreMContext : Microsoft.EntityFrameworkCore.DbContext
{
public Microsoft.EntityFrameworkCore.DbSet<User> Users { get; set; }
public Microsoft.EntityFrameworkCore.DbSet<AccessTime> AccessTime { get; set; }
...
}
Then I have a repository class CAccessTimeRepository
public class CAccessTimeRepository : IRepository<AccessTime>
{
private EFCoreMContext db;
public CAccessTimeRepository(EFCoreMContext context)
{
this.db = context;
}
...
with async functions:
public async Task<IEnumerable<AccessTime>> FindAsync(Func<AccessTime, bool> predicate)
{
return await db.AccessTime.Where(predicate).ToListAsync();
}
...
}
The trouble is when I try to use this ToListAsync() – Visual Studio highlights it with an error
CS1061 IEnumerable does not contain ToListAsync()
The thing is when I use .Where() with something like this
.Where(x => x.ID == 1)
it returns an IQueryable, so I can use ToListAsync(). But when I use this method with my predicate, it returns IEnumerable.
So deal with it I try to pass this code with an AsQueryable
public async Task<IEnumerable<AccessTime>> FindAsync(Func<AccessTime, bool> predicate)
{
return await db.AccessTime
.Where(predicate)
.AsQueryable()
.ToListAsync();
}
While executing this code I get an error:
The source ‘IQueryable’ doesn’t implement ‘IAsyncEnumerable<_3TierApp.DAL.Entities.AccessTime>’. Only sources that implement ‘IAsyncEnumerable’ can be used for Entity Framework asynchronous operations.
I have no idea why .Where() with my predicate and with x => x.Id returns different types.
Can somebody explain? And also what will be the best working solution for this?
>Solution :
EF Core’s extensions like EntityFrameworkQueryableExtensions.ToListAsync work with IQueryable interface (check out the linked method signature), not an IEnumerable and IQueryable requires Expression<Func<...>> (Queryable.Where for example) not just Func<...> (which allows to analyze passed expression tree and generate SQL query), so change the signature accordingly:
public async Task<IEnumerable<AccessTime>> FindAsync(
Expression<Func<AccessTime, bool>> predicate)
{
return await db.AccessTime
.Where(predicate)
.ToListAsync();
}
Read more:
- What is the difference between
IQueryable<T>andIEnumerable<T>? - Expression trees
- EF Core: How Queries Work