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.
This is a known bug fixed in 3.1. 3.0 is almost unusable due to all regressions after the query pipeline rewrite.
I recommend following the issue tracker on github for ef core.
https://github.com/dotnet/efcore/pull/17599
When you cast to IEnumerable() or List() EFCore forces Client side evaluation, which is why it works. (but works at a performance cost)
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!
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