[CSHARP-4852] Linq3Provider does not deal correctly with non-existing objects Created: 21/Nov/23 Updated: 19/Dec/23 Resolved: 19/Dec/23 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Unknown |
| Reporter: | Sjoerd Grevelink | Assignee: | Robert Stam |
| Resolution: | Works as Designed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||
| Documentation Changes Summary: | 1. What would you like to communicate to the user about this feature? |
||||||||
| Description |
| Comments |
| Comment by Robert Stam [ 19/Dec/23 ] | ||||||||||||||||||
|
> If you check the Render() of the projection, you will see that it renders these as $ne / $eq for != null / == null and $in with "" and null for string.IsNullOrEmpty. This however misses the "$UNSET" that is needed for non-existence of the field. I explained in point 3 above that we chose not to require the MQL resulting from translation C# LINQ expressions to handle the case of missing fields. If you think a field might be missing you should account for that in your query. | ||||||||||||||||||
| Comment by Sjoerd Grevelink [ 29/Nov/23 ] | ||||||||||||||||||
|
I would also like to suggest:
| ||||||||||||||||||
| Comment by Sjoerd Grevelink [ 29/Nov/23 ] | ||||||||||||||||||
|
Thanks for looking into this, Robert, and thanks for the update. I would personally prefer an option to follow the settings on the BSON class map, but the biggest issue is that there is currently no way to test for the missing fields. I look forward to your addition of those helper methods. | ||||||||||||||||||
| Comment by Robert Stam [ 28/Nov/23 ] | ||||||||||||||||||
|
Thank you for reporting this issue. I am able to reproduce the behavior you have reported. There are several related issues going on here: 1. Client-side vs server-side projection When using LINQ2 the Find Projection is executed client side, but when using LINQ3 the projection is executed server-side. A missing OptionalData field is deserialized as null so when executing client-side the predicate "main.OptionalData == null" will be true when OptionalData is missing. But when executing server side "main.OptionalData == null" is translated as " { $eq : ["$OptionalData", null] }" which according to server semantics for $eq is not true for a missing field. 2. Client-side projections should be explicit when using LINQ3 You could convert your Find to use explicit client-side projection instead of server-side projection. This is done by writing the query in a way that separates what happens server-side from what happens client-side. Your query could be re-written like this:
3. We chose to make testing for missing fields the application's responsibility in LINQ queries The reason we made this choice is to benefit applications that don't have missing fields. The query translations will be simpler and will execute faster. If the application expects fields to be missing it should test for that explicitly and decide what a missing field means. 4. Unfortunately we have not yet provided a way to test if a field is missing I will find or create a JIRA ticket for this functionality and link this ticket to it. Most likely this will involve custom static methods that our LINQ3 provider will recognize and translate. The idea is that instead of writing:
You would write something like:
or:
| ||||||||||||||||||
| Comment by Sjoerd Grevelink [ 21/Nov/23 ] | ||||||||||||||||||
|
If you check the Render() of the projection, you will see that it renders these as $ne / $eq for != null / == null and $in with "" and null for string.IsNullOrEmpty. This however misses the "$UNSET" that is needed for non-existence of the field. | ||||||||||||||||||
| Comment by PM Bot [ 21/Nov/23 ] | ||||||||||||||||||
|
Hi sgrevelink@gmail.com, thank you for reporting this issue! The team will look into it and get back to you soon. |