I've got the following data layer setup:
public class Repository : IRepository {
private readonly MyDbContext _dbContext;
public List<Meter> Search(Expression<Func<Meter,bool>> criteria)
IQueryable<Meter> results = _dbContext.Meters;
return results.Where(criteria).ToList();
}
}
}
... from a client class:
IRepository _repository;
public void ClientMethod () {
ICollection<int> ids = new List<int>() {1, 2, 3);
var results = _repository.Search(c=> ids.Contains(c.Id)); // This throws exception
}
This results in the exception:
expression Where(source: DbSet, predicate: (m) => (Unhandled parameter: __ids_0).Contains(m.Id))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()
But if I change the collection reference to IEnumerable or List, it works:
public void ClientMethod () {
// This works
List<int> ids = new List<int>() {1, 2, 3);
var results = _repository.Search(c=> ids.Contains(c.Id));
// This works
IEnumerable<int> ids = new List<int>() {1, 2, 3);
var results = _repository.Search(c=> ids.Contains(c.Id));
}
Why is it not working for ICollection, but it does for IEnumerable and List? Many of my client methods take an ICollection as a parameter.
I'm using EF Core 3.0 but I believe I had the same problem in 2.1, it just didn't throw as it evaluated it on the client instead.
I've run into the same issue, when migrating to EF Core 3.0 from 2.2. I've had ef configured before to throw error on client side evaluation, and it was working fine. So I'm sure it's a new issue with 3.0, introduced when they've rewritten the linq engine.
Casting it to either IEnumerable or List works for me as well, thanks for the tip!