[CSHARP-4705] ExpressionNotSupportedException with projection expression Created: 03/Jul/23  Updated: 27/Oct/23  Resolved: 01/Sep/23

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

Type: Bug Priority: Unknown
Reporter: Loris Blanchon 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:
Duplicate
duplicates CSHARP-4763 Consider supporting client side proje... Scheduled
Related
related to CSHARP-4779 Support Dictionary(IEnumerable<KeyVal... Scheduled
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

After upgrading the MongoDB C# driver from 2.15.0 to 2.20.0, I am getting ExpressionNotSupportedException for one of my queries. I am running MongoDB 5.0.18.

How to Reproduce

I have the following object:

 

public class UnlockableModel
{
    [BsonId]
    public Guid profileId { get; set; }
    public Dictionary<String, List<String>> entries { get; set; }
}

The following query will fail with ExpressionNotSupportedException:

List<string> categories = new List<string> {"Test"};
 
var filter = Builders<UnlockableModel>.Filter.Eq(model => model.profileId, profileId);
var options = new FindOptions<UnlockableModel>
{
    Projection = Builders<UnlockableModel>.Projection.Expression(p => new UnlockableModel
    {
        profileId = p.profileId,
        entries = (p.entries != null) ? new(p.entries.Where(kvp => categories.Contains(kvp.Key))) : new()
    })
};
 
var result = await _unlockableCollection.FindAsync(filter, options);

Downgrading the connection to LinqProvider.V2 fixes the issue:

var connectionString = "mongodb://localhost";
MongoClientSettings settings = MongoClientSettings.FromConnectionString(connectionString);
settings.LinqProvider = LinqProvider.V2;



 Comments   
Comment by Robert Stam [ 01/Sep/23 ]

You are correct that for now the correct workaround is to do the projection client-side.

LINQ3 does support a robust set of projections server-side (as long as you are using server 4.4 or newer), but in this particular case you are using a `Dictionary` constructor that LINQ3 doesn't support:

 

Dictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) 

I have created a separate ticket for that feature.

 

Comment by Loris Blanchon [ 04/Jul/23 ]

I was able to fix the exception by doing the projection client-side as suggested in CSHARP-4498:

List<string> categories = new List<string> {"Test"};
 
var filter = Builders<UnlockableModel>.Filter.Eq(model => model.profileId, profileId);
 
var result = await _unlockableCollection.FindAsync(filter);
 
UnlockableModel model = result.FirstOrDefault() ?? new UnlockableModel();
model.entries = (model.entries != null) ? new(model.entries.Where(kvp => categories.Contains(kvp.Key))) : new();

Please let me know if it is the correct fix.

Comment by PM Bot [ 03/Jul/23 ]

Hi loris.blanchon@ubisoft.com, thank you for reporting this issue! The team will look into it and get back to you soon.

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