I'm a newbie that just recently started using EF Core 5 for a project and am encountering an issue with the following query:
TimeSpan bookTimeToLive = TimeSpan.FromHours(10);
IList<Book>? expiredBooks = dbContext.Value.Books.AsQueryable()
.Where(x => DateTime.UtcNow - x.UtcTimeStamp > bookTimeToLive)
.ToList();
// Get list of expired Books to remove them
dbContext.Value.RemoveRange(expiredBooks);
await dbContext.Value.SaveChangesAsync(cancellationToken);
My goal is to remove all Books that are expired (their timestamp is past the amount of time I want to keep track of them for).
With that, I get the exception:
The LINQ expression 'DbSet<Books>()
.Where(d => DateTime.UtcNow - d.UtcTimeStamp > __bookTimeToLive_0)' 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 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See
https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Upon some digging, I realized that this is because EF is unable to parse my DateTime comparison into the SQL query, so I attempted to use the DbFunctions.DateDiffHour() method from https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.sqlserverdbfunctionsextensions.datediffhour?view=efcore-5.0#Microsoft_EntityFrameworkCore_SqlServerDbFunctionsExtensions_DateDiffHour_Microsoft_EntityFrameworkCore_DbFunctions_System_DateTime_System_DateTime _
The issue now is that even though I have the Nuget EF Core 5 installed and imported in my class, I can not access any of the DbFunctions methods:
The same applies to EF.Functions (no public methods):
Is this perhaps a bug or am I not using these classes properly? Is this the right approach for what I want to accomplish? Cheers!
If the time component is static (same for all rows) then a simple option is to apply it to the current date to form a cutoff to compare against:
Instead of:
TimeSpan bookTimeToLive = TimeSpan.FromHours(10);
IList<Book> expiredBooks = dbContext.Value.Books
.Where(x => DateTime.UtcNow - x.UtcTimeStamp > bookTimeToLive)
.ToList();
Something like this. No need for DbFunctions.
DateTime expiryCutoff = DateTime.UtcNow.AddHours(-10);
Ilist<Book> expiredBooks = dbContext.Books
.Where(x => x.UtTimeStamp < expiryCutoff)
.ToList();
If it is dynamic, DateTime
methods like AddHours
will still translate:
Ilist<Book> expiredBooks = dbContext.Books
.Where(x => x.UtTimeStamp.AddHours(x.ExpiryCutoff) < DateTime.UtcNow)
.ToList();
Where ExpiryCutoff is a data-driven value in the record. (or a related expression)
Alternatively, can we just use the DateTime
object and rewrite your original query?
IList<Book>? expiredBooks = dbContext.Value.Books
.Where(x => x.UtcTimeStamp.addHours(10) > DateTime.UtcNow)
.ToList();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.