Dictionary support for translation .Item["key"]

XMLWordPrintableJSON

    • Type: Improvement
    • Resolution: Works as Designed
    • Priority: Major - P3
    • None
    • Affects Version/s: 2.10.0
    • Component/s: LINQ
    • None
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      We're using the [Microsoft Expression|https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/how-to-use-expression-trees-to-build-dynamic-queries] to query the mongoDb dynamically using the C# Driver.

      So far this was working out pretty well, but in the following scenario we're running into trouble:

      // C# Model
      public class Item{
        public Name { get; set; }
        public Dictionary<string, Property> Properties { get; set; }
        ...
      }
      
      public class Property {
        public dynamic Value { get; set; }
        ...
      }

      Our configuration translates this into the following JSON in the Database (using the fluent class mapping)

      // JSON in MongoDB
      {
        "Name": "Door",
        "Properties": {
          "Color": {
            "Value": "Red",
            ...
          },
          "Height": {
            "Value": 300,
            ...
          },
          ...
        },
        ...
      }
      

      We can query it in MongoDB shell easily as:

      // Mongo shell
      db.getCollection('test_collection').find({'Properties.Color.Value': 'Red'})

      And even in c# we can query it in link as:

      // C# Linq query
      test_collection
        .AsQueryable()
        .Where(x => x.Properties["Color"].Value as string == "Red")
        .SingleOrDefault();
      

      So far so good, this is all working nice and properly, but now comes the tricky part. The dynamic expression:

      // Don't you mind this big lumb of code, but might be usefull for other readers, cause it took us a while to craft this:
      
      var parameterExpression = Expression.Parameter(typeof(T), "x");
      var properties = Expression.Property(parameterExpression, "Properties");
      var propertyInfo = typeof(Dictionary<string,EntityProperty>).GetProperty("Item");
      var arguments = new List<Expression> { Expression.Constant("Color") };
      var indexer = Expression.MakeIndex(properties, propertyInfo, arguments);
      var valueProperty = Expression.Property(indexer, "Value");
      var compareValue = Expression.Constant("Red");
      var converted = Expression.Convert(valueProperty, typeof(string));
      var expression = Expression.MakeBinary(ExpressionType.Equal, converted, compareValue);
      var lambda =  Expression.Lambda<Func<T, bool>>(expression, parameterExpression);
      
      // What this basicially does, it generates a lambda expression dynamically,
      // however the format is the following:
      
      // x => x.Properties.Item["Color"].Value == "Red"

      If we pass this query to a local List<Item> the objects are filtered perfectly,
      however when we pass this to mongodb, it gives me an error on {document}{Properties}.Item

      test_collection   //IMongoCollection<Item>
        .AsQueryable()
        .Where(lambda)
        .SingleOrDefault();

      Question: Should MongoDB c# driver support dynamically created Expressions for Dictionaries?

      ------------------------------------------
      Notes:

      • Dynamic expresions are working fine without Dictionaries (i.e. we filter on Name)
      • The .Item is the only Way to build dynamic expressions on a dictionary
      • Not sure if this is a feature request, or a bug...

            Assignee:
            Dmitry Lukyanov (Inactive)
            Reporter:
            Roel Bruins
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: