[CSHARP-4651] LINQ3 provider: MongoDB.Driver.Linq.ExpressionNotSupportedException: Expression not supported: 1 in (1 == 1) Created: 11/May/23  Updated: 28/Oct/23  Resolved: 16/May/23

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

Type: Bug Priority: Minor - P4
Reporter: Roberto Pérez Assignee: Robert Stam
Resolution: Fixed Votes: 0
Labels: None
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   

Summary

The latest MongoDB.Driver for C# switched the default LINQ Provider from 2 to 3. After trying to upgrade and use version 3 the code that used to work in V2 fails in V3.

Server versions: 5.0.13 Windows and 5.0.10 Ubuntu

How to Reproduce

See comments below



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

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4651: Fix bug in PartialEvaluator.
Branch: v2.19.x
https://github.com/mongodb/mongo-csharp-driver/commit/fecef656d1d4eb867a3055faf5548633d07c1c8b

Comment by Githook User [ 16/May/23 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4651: Fix bug in PartialEvaluator.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/fab50cd359c49f0c1a68dfe08ea1d71cfb3963ea

Comment by Roberto Pérez [ 12/May/23 ]

Thank you robert@mongodb.com 

Comment by Robert Stam [ 12/May/23 ]

Thank you for reporting this. I have found the cause and fixed it.

Note that LINQ2 and LINQ3 produce different MQL for your test cases. The MQL produced by LINQ3 is more optimized.

 

Comment by Roberto Pérez [ 11/May/23 ]

Output:

V2 - Description for license: 5555XXX

No description available for trucks

V3 - Description for license: 5555XXX

Unhandled Exception: MongoDB.Driver.Linq.ExpressionNotSupportedException: Expression not supported: 1 in (1 == 1) because it was not possible to determine how to serialize the constant.
   at MongoDB.Driver.Linq.Linq3Implementation.Misc.SerializationHelper.SerializeValue(IBsonSerializer serializer, ConstantExpression constantExpression, Expression containingExpression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.BinaryExpressionToAggregationExpressionTranslator.TranslateConstant(BinaryExpression containingExpression, ConstantExpression constantExpression, IBsonSerializer otherSerializer)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.BinaryExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, BinaryExpression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, Expression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ConditionalExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, ConditionalExpression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, Expression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MemberInitExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, MemberInitExpression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, Expression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(TranslationContext context, LambdaExpression lambdaExpression, IBsonSerializer parameterSerializer, Boolean asRoot)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToPipelineTranslators.SelectMethodToPipelineTranslator.Translate(TranslationContext context, MethodCallExpression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToPipelineTranslators.ExpressionToPipelineTranslator.Translate(TranslationContext context, Expression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToExecutableQueryTranslators.ExpressionToExecutableQueryTranslator.Translate[TDocument,TOutput](MongoQueryProvider`1 provider, Expression expression)
   at MongoDB.Driver.Linq.Linq3Implementation.MongoQuery`2.Execute()
   at MongoDB.Driver.Linq.Linq3Implementation.MongoQuery`2.GetEnumerator()
   at Sample.Program2.Main(String[] args) in D:\tfs2015\Shared\Packages\Panda.DataAccess\Sample\Program2.cs:line 49

Comment by Roberto Pérez [ 11/May/23 ]

    internal class Program2
    {
        private static void Main(string[] args)
        {
            foreach (var linqProvider in new []{ LinqProvider.V2, LinqProvider.V3})
            {
                var builder = new MongoUrlBuilder
                {
                    DatabaseName = "Sample",
                    Server = new MongoServerAddress("localhost", 27017)
                };
                var mongoClientSettings = MongoClientSettings.FromUrl(builder.ToMongoUrl());
                mongoClientSettings.LinqProvider = linqProvider;
                var mongoClient = new MongoClient(mongoClientSettings);
                var mongoDatabase = mongoClient.GetDatabase(builder.DatabaseName);
 
                var carLicensePlate = "5555XXX";
                var truckLicensePlate = "6666YYY";
 
                var carCollection = mongoDatabase.GetCollection<Car>("Cars");
                carCollection.DeleteMany(c => true);
                carCollection.InsertOne(new Car
                {
                    Id = carLicensePlate,
                    Description = $"{linqProvider} - Description for license: {carLicensePlate}",
                    VehicleType = VehicleType.Car
                });
                carCollection.InsertOne(new Car
                {
                    Id = truckLicensePlate,
                    Description = $"{linqProvider} - Description for license: {truckLicensePlate}",
                    VehicleType = VehicleType.Truck
                });
 
                foreach (var car in carCollection.AsQueryable()
                             .Where(c => c.VehicleType == VehicleType.Car)
                             .Select(ToCustomProjection_Works(VehicleType.Car)))
                {
                    Console.WriteLine(car.Description);   
                }
                Console.WriteLine();
                foreach (var car in carCollection.AsQueryable()
                             .Where(c => c.VehicleType == VehicleType.Truck)
                             .Select(ToCustomProjection_Fails(VehicleType.Truck)))
                {
                    Console.WriteLine(car.Description);
                }
                Console.WriteLine();
                Console.WriteLine();
            }
        }
 
        private static Expression<Func<Car, CarDto>> ToCustomProjection_Works(VehicleType vehicleType)
        {
            var isTruck = vehicleType == VehicleType.Truck;
            return c => new CarDto
            {
                Id = c.Id,
                Description = isTruck ? "No description available for trucks" : c.Description
            };
        }
 
        private static Expression<Func<Car, CarDto>> ToCustomProjection_Fails(VehicleType vehicleType)
        {
            return c => new CarDto
            {
                Id = c.Id,
                Description = vehicleType == VehicleType.Truck ? "No description available for trucks" : c.Description
            };
        }
 
        private enum VehicleType
        {
            Car = 0,
            Truck = 1
        }
 
        private class Car
        {
            public string Id { get; set; }
            public string Description { get; set; }
            public VehicleType VehicleType { get; set; }
        }
 
        private class CarDto
        {
            public string Id { get; set; }
            public string Description { get; set; }
        }
    }

Comment by PM Bot [ 11/May/23 ]

Hi suikevil, thank you for reporting this issue! The team will look into it and get back to you soon.

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