Skip to content

DateTimeOffset expression could not be translated in EF.Sqlite 2.2.0 #14082

Description

@YZahringer

Simple LINQ query could not be translated in EF.Sqlite 2.2:

queryable.Where(e => e.CreationDate > DateTimeOffset.Now)

It worked with EF.Sqlite 2.1 and EF.SqlServer 2.2.

Exception message:
System.InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The LINQ expression 'where ([e].CreationDate > DateTimeOffset.Now)' could not be translated and will be evaluated locally.'.
Stack trace:
   at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition`1.Log[TLoggerCategory](IDiagnosticsLogger`1 logger, WarningBehavior warningBehavior, TParam arg, Exception exception)
   at Microsoft.EntityFrameworkCore.Internal.RelationalLoggerExtensions.QueryClientEvaluationWarning(IDiagnosticsLogger`1 diagnostics, QueryModel queryModel, Object queryModelElement)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.WarnClientEval(QueryModel queryModel, Object queryModelElement)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
   at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
   at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileAsyncQuery[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQueryCore[TResult](Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass22_0`1.<CompileAsyncQuery>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddAsyncQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQuery[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator()
   at System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](IAsyncEnumerable`1 source, TAccumulate seed, Func`3 accumulator, Func`2 resultSelector, CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Aggregate.cs:line 118

Further technical details

EF Core version: 2.2.0
Database Provider: Microsoft.EntityFrameworkCore.Sqlite
Operating system: Windows 10 1803
IDE: Visual Studio 2017 15.9.3

Activity

  1. changed the title [-]DateTime expression could not be translated in EF.Sqlite 2.2.0[/-] [+]DateTimeOffset expression could not be translated in EF.Sqlite 2.2.0[/+] on Dec 5, 2018
  2. smitpatel commented on Dec 5, 2018

    @smitpatel
    Contributor

    SQLite does not have any type mapping or operations involving DateTimeOffset on server.

  3. bricelam commented on Dec 7, 2018

    @bricelam
    Contributor

    It was broken in 2.1--values with different offsets were compared incorrectly. We fixed it in 2.2 to compare the values on the client.

  4. YZahringer commented on Dec 7, 2018

    @YZahringer
    Author

    @bricelam Thank you for the details. To make queries on Sqlite I have to store them in DateTime?

  5. divega commented on Dec 7, 2018

    @divega
    Contributor

    @YZahringer yes, that is the best approach with SQLite.

  6. YZahringer commented on Dec 8, 2018

    @YZahringer
    Author

    I use the same model on different SQL Providers, which support DateTimeOffset.

    I was thinking of adding a conversion to DateTime when it's Sqlite, but it does not work, the Query is still evaluated client side. Something is wrong?

    if (IsSqlite)
    {
        modelBuilder.Entity<MyEntity>().Property(e => e.CreationDateTimeOffset).HasConversion(
            dateTimeOffset => dateTimeOffset.UtcDateTime,
            dateTime => new DateTimeOffset(dateTime));
    }
  7. divega commented on Dec 8, 2018

    @divega
    Contributor

    Reopening so that we can follow on on why type conversions don’t help. The original issue is still by-design.

  8. reopened this on Dec 8, 2018
  9. smitpatel commented on Dec 8, 2018

    @smitpatel
    Contributor

    @divega
    Duplicate of #13192

  10. smitpatel commented on Dec 8, 2018

    @smitpatel
    Contributor

    There are few issues here in using value conversion.

    • At translation time we do no infer types, we only do that during printing out SQL. So even if you have value converter on the property which query would find out from property, the other side (if constant or parameter) still calls it out DateTimeOffset and block translation from going to server. (Issue Query: Infer TypeMapping for Literals & Parameters correctly #13192)
    • In above case DateTimeOffset.Now being server evaluated always, SQLite does not have translation for that. So even though we try to use value converter after above issue is fixed, now we need to find translation of DateTimeOffset.Now.UtcDateTime. Which we may be able to condense to DateTime.Now (though not necessary we can do that for any value converter. This is covered by Support (custom) member/method translations on value-converted types #10434
  11. ajcvickers commented on Dec 15, 2018

    @ajcvickers
    Contributor

    @bricelam I tried a variety of different "casts" but could not get anything to work. Do you want to give it a try?

  12. bricelam commented on Jan 2, 2019

    @bricelam
    Contributor

    I hoped that with the conversion, a query like this would work translate:

    queryable.Where(e => (DateTime)e.CreationDateTimeOffset > DateTime.UtcNow)
  13. sebastianfilke commented on Feb 10, 2019

    @sebastianfilke

    So what can we do now? We are stuck on the old version because in our whole application is DateTimeOffset. Is there any workaround or solution? Will there be a fix?

  14. mqudsi commented on Jul 11, 2019

    @mqudsi

    @smitpatel any chance of revisiting this now that you've closed #13192?

    If you just treat the SQLite database as a UTC DateTimeOffset (e.g. any incoming DateTimeOffset gets converted to the UTC DateTime, any outgoing gets converted back to DateTimeOffset with offset +0) then courtesy of #13192 you should also be able to handle comparisons, assignments, etc. to local DateTimeOffset values by converting them to their UTC DateTime values first before binding to the query?

  15. smitpatel commented on Jul 11, 2019

    @smitpatel
    Contributor

    Deferring to @bricelam. It may not be just about offset.

  16. bricelam commented on Jul 11, 2019

    @bricelam
    Contributor

    I think we have an issue about allowing translations after a value conversion. We should consider this scenario.

    Note that you lose the original time zone information when you do this so we wouldn’t do it by default.

  17. RaduTofan commented on Jul 5, 2021

    @RaduTofan

    instead of
    queryable.Where(e => e.CreationDate > DateTimeOffset.Now)

    try this
    queryable.Where(e => e.CreationDate.CompareTo(DateTimeOffset.Now) > 0)

    worked for me

  18. mqudsi commented on Jul 5, 2021

    @mqudsi

    @bricelam should there be a difference between the two in the example @RaduTofan posted?

  19. bricelam commented on Jul 6, 2021

    @bricelam
    Contributor

    Neither one should work. 😏 But the second one is more likely to evaluate on the client in older versions of EF Core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions