[CSHARP-4510] Several expressions no longer translate as expected, even in v2 Created: 01/Feb/23  Updated: 09/Mar/23  Resolved: 09/Mar/23

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 2.19.0
Fix Version/s: None

Type: Bug Priority: Unknown
Reporter: Fred Morel Assignee: Robert Stam
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates CSHARP-4499 Support Convert calls to a base type ... Closed
Related
is related to CSHARP-4543 Unsupported expression - negative ind... Closed
Documentation Changes Summary:

1. What would you like to communicate to the user about this feature?
2. Would you like the user to see examples of the syntax and/or executable code and its output?
3. Which versions of the driver/connector does this apply to?


 Description   

Summary

Since 2.19 now defaults to LINQ V3, I now have several broken queries, which I expected. However, some of them still fail when I switch back to the LINQ V2 translator.

Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

2.19

How to Reproduce

Steps to reproduce. If possible, please include a Short, Self Contained, Correct (Compilable), Example.

 

private static string GetFieldName<TDocument>(Expression<Func<TDocument, object>> expression)
    where TDocument : class
{
    var def = new ExpressionFieldDefinition<TDocument, object>(expression);
    var rendered = def.Render(BsonSerializer.LookupSerializer<TDocument>(), BsonSerializer.SerializerRegistry, true);
    return rendered.FieldName;
}
 
[Fact]
public void GetFieldName_NestedValue()
{
    var field = GetFieldName<Foo>(x => x.Subdocument.NestedProperty);
    Assert.Equal("Subdocument.NestedProperty", field);
}
 
[Fact]
public void GetFieldName_ArrayWithIndex()
{
    var field = GetFieldName<Foo>(a => a.ArrayField[-1]);
    Assert.Equal("ArrayField.$", field);
} 

 

 

Additional Background

The $ array one tells me to use `.FirstMatchingElement()` instead, which is fine for transitioning to v3 but I didn't expect v2 to start failing.

The nested property one throws :

MongoDB.Driver.Linq.ExpressionNotSupportedException
Expression not supported: Convert(x.Subdocument.NestedProperty, Object).

It starts working if I pass in a 2nd type to my helper for the field type to use instead of `object`...but I don't want to have to specify the type every time.

 

These changes in behavior on V2 lead to me having to schedule time to do a thorough audit of our use of Mongo to avoid runtime problems that may not be caught by tests.



 Comments   
Comment by Robert Stam [ 23/Feb/23 ]

There are no changes to the driver in this code review. Only new tests to verify that the examples supplied work (not what CSHARP-4499 was fixed).

Comment by Robert Stam [ 23/Feb/23 ]

I have confirmed that:

CSHARP-4499 fixes the `ExpressionNotSupportedException` you were seeing
Using -1 to mean `$` still works in LINQ2 provided you call Render with LinqProvider.V2
Using FirstMatchingElement to mean `$` works in LINQ3 provided you call Render with LinqProvider.V3

Thanks again for reporting this issue.

Comment by Fred Morel [ 02/Feb/23 ]

When the driver itself calls `Render` it always passes in the `linqProvider` (assuming it knows it), but if you call `Render` yourself you have to pass in the `linqProvider` yourself.

 

Oh. Thank you for pointing that out. That helps me create a way to migrate most things.

Comment by Robert Stam [ 01/Feb/23 ]

This is similar to CSHARP-4509 (and I'm pretty sure the fix to CSHARP-4509 will fix this also).

One thing different here is that you are calling `Render` directly. There is another overload of `Render` that takes a `LinqProvider` argument. Since the default is now LINQ3 if you want to render something using LINQ2 you have to pass in a `linqProvider` argument.

When the driver itself calls `Render` it always passes in the `linqProvider` (assuming it knows it), but if you call `Render` yourself you have to pass in the `linqProvider` yourself.

Generated at Wed Feb 07 21:48:26 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.