EF Linq Error after change from dotnet Core 2.2.6 to 3.0.0

monsee picture monsee · Sep 24, 2019 · Viewed 50.4k times · Source

I'm trying to upgrade a solution to the new Core Framework 3.0.0. Now I'm having a small issue I don't understand.

Look, this method was unproblematic in 2.2.6:

public async Task<IEnumerable<ApplicationUser>> GetBirthdayUsersCurrentMonth()
    {
        return await ApplicationDbContext.Users
            .Where(x => x.Gender != ApplicationUser.GenderTypes.generic)
            .Where(x => x.BirthDate.GetValueOrDefault().Month == DateTime.Now.Month)
            .Where(x => x.RetireDate == null)
            .OrderBy(x => x.BirthDate.GetValueOrDefault())
            .ToListAsync();
    }

Now in 3.0.0 I get a Linq Error saying this:

InvalidOperationException: The LINQ expression 'Where( source: Where( source: DbSet, predicate: (a) => (int)a.Gender != 0), predicate: (a) => a.BirthDate.GetValueOrDefault().Month == DateTime.Now.Month)' 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()

When I disable this line:

.Where(x => x.BirthDate.GetValueOrDefault().Month == DateTime.Now.Month)

The error is gone but off course I get all users. And I can't see an error in this query. Could this perhaps be a bug in EF Core 3.0.0?

Answer

Daniel Hilgarth picture Daniel Hilgarth · Sep 24, 2019

The reason is that implicit client evaluation has been disabled in EF Core 3.

What that means is that previously, your code didn't execute the WHERE clause on the server. Instead, EF loaded all rows into memory and evaluated the expression in memory.

To fix this issue after the upgrade, first, you need to figure out what exactly EF can't translate to SQL. My guess would be the call to GetValueOrDefault(), therefore try rewriting it like this:

.Where(x => x.BirthDate != null && x.BirthDate.Value.Month == DateTime.Now.Month)