-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom scalar database function sometimes evaluated on client #14002
Comments
The functions will be evaluated on the client if something else in the query forces client evaluation. Pulling back that entire entity must be causing client eval, though I'm not sure why. Does the sql look correct if you run the first example without the 2 function calls? |
I also thought, that something on entity may cause that client evaluation. That's why I first tried to retrieve just one column from it, later added more of them and it turned out that even query with all columns from that table works. But only if they are named explicitly. |
Yes a small repo project would be useful to track down the issue. cc: @smitpatel - he might already have run into this. |
Duplicate of #11186 |
Thank you very much for your help. I will prepare small repo for it (I wonder if it can be reproduce even outside of project). In scenario when EF is not able to include custom scalar function call into query I would expect that it will run a separate query (just like in #11186) and not do evaluation on client. I might be wrong, but I think, it is very likely that custom scalar function will not have any client side fallback implementation (in my case just an exception is thrown as implementation). From performance perspective it is of course not the best but at least it would work. |
@ajcvickers I found root cause of this problem. When a query is divided into subquery (and DBFunctiion is used in SELECT clause), client evaluation is performed while joining results at client. For example, var customers = db.Customers.Where( ... )
.Select( x => new {
// this will be executed in server
Property = DbFunctions.Some( ... ) ,
Orders = x.Orders
.Where( ... )
.Select( o => new {
// when you call dbfunction with parameters from customer and order
// this will be executed at client
OrderProperty = DbFunctions.Some ( x.CustomerProperty, o.OrderProperty)
} )
} ) The only solution to this is, Static function should contain logic for client side evaluation. [DbFunction("MaxDate")]
public static DateTime? MaxDate( DateTime? d1, DateTime? d2) {
// this is wrong...
// throw new NotSupportedException();
// this is correct...
return d1 > d2 ? d2 : d1;
} DbFunction static must contain appropriate logic for client side evaluation, this is required for splitting subqueries as well as in memory unit testing. |
@ackava duplicating code is not an option and I would not make it a recommendation or any official preferred approach. It is maintenance nightmare in enterprise applications to have the same code twice. One possible workaround is to have .NET implementation of function installed as CLR code also in SQL server so T-SQL implementation will be replaced by SQL .NET CLR version (without breaking other T-SQL code). But this approach works also only for simplier cases (function/procedures without DB access). In this particular case (until official solution is available), we will either separate this query into two DB calls or pull required entities by naming their attributes instead of pulling whole entities (since that works properly). |
@martin-hronsky I definitely agree with maintenance nightmare. The problem lies with @ajcvickers |
@smitpatel to follow up |
The underlying issue for this particular case has been fixed in #11186. Given client eval is only supported in projection, we try to evaluate as much of projection code on server side as possible, hence DbFunction will translate to server when possible. The only case where that is not the case is if the arguments of DbFunction are causing client evaluation. In such case, it is ok to call into client code or throw exception because we cannot improve the scenario in any other way. |
Closing this as duplicate. Additional notes:
|
I have strange issue when call custom database function added to the Db context.
In following query:
both functions are evaluated on client.
The same query, but without retrieving table "b":
results in proper SQL statement - both database function calls are included in the query.
Even more strange is that when I query for all "b" table columns by naming them explicitly (instead of asking for "b" table):
both database function calls are properly included in the SQL statment.
We are using EF Core v 2.1.3 against SQL Server 2012 database.
The text was updated successfully, but these errors were encountered: