Skip to content

SQL translation should be more generic and operate on end results #12552

@mqudsi

Description

@mqudsi

Following up on the discussion in #12517, I believe there's a fundamental issue with the way SQL translation is currently handled. If there is an expression that cannot be directly mapped to an SQL equivalent, but that expression evaluates to a data type that can be directly plugged in to an SQL query, then that expression should be evaluated and its result used instead of the SQL translation giving up and the query being evaluated locally rather than on the database server.

To illustrate with a concrete example:

    public class Database : DbContext
    {
        ....
        public IQueryable<Listing> ActiveListings => Listings
            .Where(x => x.Status != ListingStatus.Sold)
            .OrderByDescending(x => x.RenewTime)
            .Where(x => x.RenewTime > DateTime.UtcNow.AddDays(-7));
    }

In the latest published EFCore w/ SQLite provider releases, this cannot be evaluated in the database as AddDays(xx) does not have a translation implemented.

However, simply doing the following makes SQL translation work and the query is fully evaluated on the DB server rather than the ASP.NET Core host:

    public class Database : DbContext
    {
        ....
        DateTime ExpiryCompare => DateTime.UtcNow.AddDays(-7);
        public IQueryable<Listing> ActiveListings => Listings
            .Where(x => x.Status != ListingStatus.Sold)
            .OrderByDescending(x => x.RenewTime)
            .Where(x => x.RenewTime > ExpiryCompare);
    }

More generally, if the translation of a given subexpression does not have a translation expressly provided by the provider, and that subexpression does not depend on the value of the record being evaluated (i.e. for a lambda x => x == Foo(..), Foo does not utilize the value of x) and the return type of Foo(...) can be used to directly evaluate the expression on the database server, then that subexpression should be evaluated and its result plugged in before translation is attempted once more.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions