[CSHARP-4622] Error with MongoDB .NET driver 2.19.0: $expr not allowed in query predicate for upsert Created: 19/Apr/23  Updated: 28/Oct/23  Resolved: 05/May/23

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

Type: Bug Priority: Blocker - P1
Reporter: Hardik Shah Assignee: Oleksandr Poliakov
Resolution: Fixed Votes: 0
Labels: triage
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible
Documentation Changes: Not Needed
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   

I am encountering an issue with the latest version (2.19.0) of the MongoDB .NET driver. When performing an upsert operation using the ReplaceOneAsync method with an Expression<Func<T, bool>> filter that always returns true, the following error occurs:

MongoDB.Driver.MongoWriteException: A write operation resulted in an error. WriteError:

{ Category : "Uncategorized", Code : 224, Message : "$expr is not allowed in the query predicate for an upsert" }

.

This error was not present in the previous version (2.18.0) of the MongoDB .NET driver.

Steps to Reproduce:

> Use the latest version (2.19.0) of the MongoDB .NET driver.
> Perform an upsert operation using the ReplaceOneAsync method with an Expression<Func<T, bool>> filter that always returns true.
> Observe the error message mentioned above.

Expected Result:
The upsert operation should complete without any error, as it did in previous versions of the MongoDB .NET driver.

Actual Result:
The upsert operation fails with the error message "$expr is not allowed in the query predicate for an upsert" in MongoDB .NET driver version 2.19.0.

Environment:

MongoDB .NET driver version: 2.19.0
Platform: Windows
.NET runtime version: .NET 6

Code snippet:
// Micro-service specific code
public async Task SyncModelNameCollection(ModelName data)

{ var updatedCount = await _db.Upsert(data, ModelName.DBCollectionName, (d) => true); }

// genric library code
public async Task<long?> Upsert<T>(T data, string collectionName, Expression<Func<T, bool>> filter)
{
var options = new ReplaceOptions

{ IsUpsert = true }

;
var result = await _db.GetCollection<T>(collectionName).ReplaceOneAsync(filter, data, options);
if (result.IsModifiedCountAvailable)

{ return result.ModifiedCount; }

return null;
}



 Comments   
Comment by Githook User [ 18/May/23 ]

Author:

{'name': 'Oleksandr Poliakov', 'email': '31327136+sanych-sun@users.noreply.github.com', 'username': 'sanych-sun'}

Message: CSHARP-4622: Process constant expression to a filter query (#1074)
Branch: v2.19.x
https://github.com/mongodb/mongo-csharp-driver/commit/3ba8dc3af955649b1f6937185fe028dd8e318fc0

Comment by Githook User [ 05/May/23 ]

Author:

{'name': 'Oleksandr Poliakov', 'email': '31327136+sanych-sun@users.noreply.github.com', 'username': 'sanych-sun'}

Message: CSHARP-4622: Process constant expression to a filter query (#1074)
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/2d11638617b49071a523bb0c8e907e17fcc019f8

Comment by Hardik Shah [ 24/Apr/23 ]

Sample C# code to replicate the issue:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
 
var settings = MongoClientSettings.FromConnectionString("mongodb://localhost:27017");
settings.LinqProvider = LinqProvider.V3; //Downgrading to V2 can solve the issue
var client = new MongoClient(settings);
var database = client.GetDatabase("SampleDB");
var collection = database.GetCollection<SampleModel>("SampleCollection");
var modelToInsertUpdate = new SampleModel() {
    SampleDate = DateTime.UtcNow,
    ChangeLookupIntervalMins = 15
};
 
try
{
    var result = await collection.ReplaceOneAsync((d) => true, modelToInsertUpdate, new ReplaceOptions { IsUpsert = true });
}
catch(Exception ex)
{
    Console.WriteLine(ex.ToString());
}
 
public class SampleModel
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    [BsonRequired]
    public string ID { get; set; }
 
    [BsonRequired]
    public DateTime SampleDate { get; set; }
 
    [BsonRequired]
    public int ChangeLookupIntervalMins { get; set; }
}

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