-
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
ToQueryString on a split query only shows the first query #22080
Comments
By design. Other queries are not executed till first query actually enumerates and find a row to materialize. This was the reason ToQueryString feature was not implemented pre-3.0 |
Note from triage: current plan is to do this when we implement query batching. |
Is there a way to get some |
@Enngage What, exactly, do you want to hash? Should it be the same if the query has different parameter values? What about constants? What about when different IQueryables generate the same SQL? Hashing a query is a complex question; even internally to EF we do it more than one way. Have you considered using query tags? https://docs.microsoft.com/en-us/ef/core/querying/tags |
@aaronralls Thank you for getting back to me so quickly! My question is probably a bit ambiguous. I was using the entire SQL query as a cache key, but this is not possible to do with the Based on the conversion above, it is not yet possible to get all SQL queries so I was hoping there is a way to get reasonably unique hash from the Tagging is a cool feature, but I don't think it helps in this case as I wouldn't know how to generate the tag in the first place. |
I just solved that issue by using ".Expression.ToString();" on the IQueryable. Gives you a string representation of the query code itself. |
@Phylum123, sadly that doesn't work because it also does not provide unique string representation of query. There are missing variables / columns and probably other things as well. For example one extremely simple query I just tried gives these results: ToQueryString()
Expression.ToString()
If, in this case, I make another query with different value in |
@Enngage That's why I asked, "What, exactly, do you want to hash?" Because typically in EF Core, the same query but a different parameter value would be considered the same query when we hash. You can write an ExpressionVistor that will traverse the expression tree and generate whatever hash you want from it, but you'll have to decide for things like parameters whether a different value signifies a different hash or not. |
@Enngage Here is the solution to your problem. I scouted around the internet, because I wanted the same solution and I beleive I found it. It essentially changes every constant or variable in the query to its actual value.
Usage:
Code:
Credit goes to the poster: Jon Skeet, who posted below the accepted answer |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
On a related noted, would it make sense to add |
@Giorgi EF doesn't actually use the DbBatch abstraction yet (e.g. in SaveChanges, where we do batch but not with DbBatch); I've been wanting to do that for a while now but haven't yet found the time (#18990). Also, split query doesn't currently batch even without DbBatch, but rather does multiple roundtrips (#10878). Once those two things are done, we can definitely expose a CreateDbBatch like we expose CreateCommand, yeah. |
Yes, I understand that it doesn't use DbBatch at the moment but because there is no way (in case of split queries) to programmatically get either query texts with |
We could; but the real work here is to expose the non-first query - exactly how one does that is less important. One important point is that currently, if the first query has no results, the second isn't even executed; so returning both queries (regardless of via DbBatch or not) wouldn't necessarily even be accurate. Once we do #10878, both queries would always be sent in any case, at which point it makes more sense to also return them in ToQueryString() or whatever. |
For the query below, ToQueryString returns
I would expect it to show all three queries that eventually get logged:
Code:
The text was updated successfully, but these errors were encountered: