-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
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')
ENDAfter implementing and using EF.Constant(), it would just look like this:
SELECT `c`.`CustomerID`
FROM `Customers` AS `c`
WHERE `c`.`CustomerID` = 'anton'