From a users perspective, is there a way to force a query that EF Core would normally client-evaluate in part (not because it needs to, but because it can), to be completely evaluated server-side?
I ask this specifically because there might be EF.Functions implementations that will only work on the server-side and will throw when client-evaluated.
The follow-up question would be, whether there are plans to support marking certain EF.Functions in a way, that EF Core is aware of the fact that those functions cannot be executed and always need to be translated (or optionally even the opposite), so it can handle them accordingly?
@lauxjpn I think you're looking for IEvaluatableExpressionFilter - it's a service that the query pipeline consults to know whether something isn't evaluatable on the client. Note how anything on DbFunctionsExtensions is automatically considered non-evaluatable.
Here's the Npgsql version (which I just noticed is missing some extensions).
BTW as a general rule, all functions under EF.Functions are expected to throw if called on the client (see this breaking change note). This is why the built-in EF Core evaluatable filters just check for those declaring types.
BTW as a general rule, all functions under EF.Functions are expected to throw if called on the client (see this breaking change note). This is why the built-in EF Core evaluatable filters just check for those declaring types.
Ah that's funny. This change is exactly about my question.
Here's the Npgsql version (which I just noticed is missing some extensions).
Thanks a lot, we have a smaller implementation of it (in 5.0 but none at all in 3.x) so I know now what I am missing there. I had recently some client eval issues while implementing additional JSON function support with tests, that forced me to provide a client eval implementation for the JSON string quoting and unquoting functions. But of course those methods reside in their own extension class, which is missing from our checks:
```c#
public override bool IsEvaluatableExpression(Expression expression, IModel model)
{
if (expression is MethodCallExpression methodCallExpression
&& methodCallExpression.Method.DeclaringType == typeof(MySqlDbFunctionsExtensions))
{
return false;
}
return base.IsEvaluatableExpression(expression, model);
}
```
Which means I can get rid of my finely crafted parsing state machine again :)
Just to give some history, it wasn't always to clear to us that we shouldn't ever provide client-side .NET implementations of these methods (I just discussed this again here: https://github.com/npgsql/efcore.pg/issues/774#issuecomment-713358922). But it's just not tenable as a general strategy to duplicate various database behavior in C#...
But it's just not tenable as a general strategy to duplicate various database behavior in C#...
I absolutely agree.
We now implemented https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/pull/1209 to fix our issues regarding this.