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

SortBy failure for dictionary entry in LinqProvider.V3

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Unknown Unknown
    • 2.19.1
    • Affects Version/s: None
    • Component/s: None
    • None
    • 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

      An exception is thrown when performing an aggregate query containing a SortBy(), whose expression is a dictionary entry.

      • This query works correctly with the V2 LinqProvider
      • The exception is: MongoDB.Driver.Linq.ExpressionNotSupportedException "Expression must be a constant"
      • The exception doesn't occur if the dictionary key is hard-coded to a constant value
      • Tested with MongoDB.Driver v2.19.0
      • I suspect this will also affect array indexes, as well as IndexKeysDefinitions

      How to Reproduce

      class Translation
      {
          public int Id { get; set; }
          public Dictionary<string, string>? Text { get; set; }
      }
      
      static List<Translation> GetSortedTranslations(IMongoCollection<Translation> collection, string language)
      {
          return collection.Aggregate()
              .SortBy(c => c.Text[language]) // This works in LinqProvider.V2, but not V3
              .ToList();
      }
      
      static List<Translation> GetTranslationsSortedByEnglish(IMongoCollection<Translation> collection)
      {
          return collection.Aggregate()
              .SortBy(c => c.Text["en"]) // This works
              .ToList();
      } 

      Additional Background

      The exception occurs when GetItemMethodToFilterFieldTranslator.TranslateWithStringIndex() calls indexExpression.GetConstantValue<string>(). GetConstantValue expects the expression to be of type ConstantExpression, whereas it is given a MemberAccess of a ConstantExpression. We may want to consider allowing partial execution, eg:

       

      public static TValue GetConstantValue<TValue>(this Expression expression, Expression containingExpression)
      {
          if (expression is ConstantExpression constantExpression)
          {
              return (TValue)constantExpression.Value;
          }
      
          LambdaExpression lambda = Expression.Lambda(expression);
          Delegate fn = lambda.Compile();
          return (TValue)fn.DynamicInvoke(null);
      } 

       

       

            Assignee:
            robert@mongodb.com Robert Stam
            Reporter:
            matthew.filby@elcome.ltd.uk Mat Filby
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: