Skip to content

Add ability to explicitly force query part evaluation during query generation #20610

@lauxjpn

Description

@lauxjpn

I believe that something like the following would be helpful in many scenarios:

var result1 = context.Customers
    .Where(c => c.Name == EF.Constant(GetMySearchCriteria()))
    .ToList();

var comparisonMode = StringComparison.OrdinalIgnoreCase;
var result2 = context.Customers
    .Where(c => string.Equals(c.Name, "Foo", EF.Constant(comparisonMode)))
    .ToList();

A method EF.Constant() is used here, to preevaluate part of the query at query build time and returns a SqlConstantExpression.

Of course this preevaluated part cannot depend on any database columns etc.

It should be communicated clearly, that whatever is in the body of this method call will be evaluated only once and at query generation time. If a clear method description is enough here, the method name could be kept relatively short, which would aid query readability, instead of giving it a long and overly descriptive name.

Some decisions would need to be made, how this affects/is affected by query caching.


This might also be useful (either explicitly for calls by users, or implicitly in providers) in conjunction with EF.Functions.Foo() methods, that take arguments that changes the behavior of the method.

Currently, if anything but a constant value is used (e.g. with string.Equals() and its comparison parameter as in the example above), then the method needs to throw or, in case the user supplied the argument using a variable, the whole method call needs to generate a CASE that evaluates the variable when the SQL is run.

See the following (intentionally simplified) SQL as an example:

@__comparison_0='2'

SELECT `c`.`CustomerID`
FROM `Customers` AS `c`
WHERE CASE
    WHEN @__comparison_0 IN (4, 0, 2) THEN `c`.`CustomerID` = 'anton'
    ELSE LCASE(`c`.`CustomerID`) = LCASE('anton')
END

After implementing and using EF.Constant(), it would just look like this:

SELECT `c`.`CustomerID`
FROM `Customers` AS `c`
WHERE `c`.`CustomerID` = 'anton'

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions