Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-4653

LINQ3 provider: MongoDB.Driver.Linq.ExpressionNotSupportedException: Expression not supported: Convert(p) because conversion to "Subclass" is not supported.

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Minor - P4 Minor - P4
    • 2.20.0
    • Affects Version/s: 2.19.1
    • Component/s: LINQ3
    • Labels:
      None
    • Fully Compatible
    • Not Needed
    • Hide

      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?

      Show
      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?

      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

          internal class Program5
          {
              public class Preference
              {
                  public Guid Id { get; set; }
                  public PreferenceType Type { get; set; }
              }        public enum PreferenceType
              {
                  EmailAlerts,
                  Another
              }        public interface IEmailAlertsPreference
              {
                  bool Enabled { get; set; }
                  string Description { get; set; }
              }        public class EmailAlertsPreference : Preference, IEmailAlertsPreference
              {
                  public EmailAlertsPreference()
                  {
                      Type = PreferenceType.EmailAlerts;
                  }            public bool Enabled { get; set; }
                  public string Description { get; set; }
              }        internal static void Main2(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 preferencesCollection = mongoDatabase.GetCollection<Preference>("Preferences");
                      preferencesCollection.DeleteMany(c => true);
                      preferencesCollection.InsertOne(new EmailAlertsPreference
                      {
                          Id = Guid.NewGuid(),
                          Enabled = true,
                          Description = $"{linqProvider} - Description"
                      });                var queryableWithoutProjection = preferencesCollection.AsQueryable()
                          .Where(p => p.Type == PreferenceType.EmailAlerts && ((EmailAlertsPreference)p).Enabled);                Console.WriteLine("*************************");
                      Console.WriteLine("Without custom projection");
                      Console.WriteLine("*************************");
                      foreach (var emailAlertsPreference in queryableWithoutProjection.ToList().Cast<EmailAlertsPreference>())
                      {
                          Console.WriteLine(emailAlertsPreference.Enabled);
                          Console.WriteLine(emailAlertsPreference.Description);
                      }
                      Console.WriteLine("*************************");
                      Console.WriteLine();                Console.WriteLine("*************************");
                      Console.WriteLine("With custom projection");
                      Console.WriteLine("*************************");
                      Expression<Func<Preference, EmailAlertsPreference>> projection = p => new EmailAlertsPreference
                      {
                          Enabled = ((EmailAlertsPreference)p).Enabled,
                          Description = ((EmailAlertsPreference)p).Description
                      };
                      foreach (var emailAlertsPreference in queryableWithoutProjection.Select(projection).ToList())
                      {
                          Console.WriteLine(emailAlertsPreference.Enabled);
                          Console.WriteLine(emailAlertsPreference.Description);
                      }
                      Console.WriteLine("*************************");
                      Console.WriteLine();
                      Console.WriteLine();
                  }
              }
          } 

      Execution output:

      *************************
      Without custom projection
      *************************
      True
      V2 - Description
      **************************************************
      With custom projection
      *************************
      True
      V2 - Description
      *************************
      *************************
      Without custom projection
      *************************
      True
      V3 - Description
      **************************************************
      With custom projection
      *************************Unhandled Exception: MongoDB.Driver.Linq.ExpressionNotSupportedException: Expression not supported: Convert(p) because conversion to Sample.Program5+EmailAlertsPreference is not supported.
         at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ConvertExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, UnaryExpression expression)
         at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.ExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, Expression expression)
         at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MemberExpressionToAggregationExpressionTranslator.Translate(TranslationContext context, MemberExpression 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 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
         at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
         at Sample.Program5.Main2(String[] args) in D:\tfs2015\Shared\Packages\Panda.DataAccess\Sample\Program5.cs:line 90
         at Sample.Program.Main(String[] args) in D:\tfs2015\Shared\Packages\Panda.DataAccess\Sample\Program.cs:line 21

            Assignee:
            oleksandr.poliakov@mongodb.com Oleksandr Poliakov
            Reporter:
            suikevil Roberto Pérez
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: