System.Linq.Dynamic.Core icon indicating copy to clipboard operation
System.Linq.Dynamic.Core copied to clipboard

Question: ContainsKey is not a standard LINQ operator

Open zspitz opened this issue 5 years ago • 3 comments

The list of LINQ standard operators supported by Dynamic LINQ includes .ContainsKey.

This list of LINQ operators doesn't include ContainsKey.

Since ContainsKey is (for all the cases I've seen) an instance method, it should not even require any special handling, because instance methods don't need to be on accessible types. Moreover, the signature for ContainsKey that I've seen always expects a single value, unlike other extension methods such as Select or SelectMany which expect a function delegate or an expression tree.

zspitz avatar Oct 23 '20 05:10 zspitz

Hello @zspitz ,

I'm currently failing to see what you really want or what you want us to change.

The ContainsKey can contain an expression such as "Orders.ContainsKey(it.City + \"TEST\")".

If you wish, feel free to make a pull request in the documentation here: https://github.com/zzzprojects/docs/tree/master/dynamic-linq.net

Best Regards,

Jon


Performance Libraries context.BulkInsert(list, options => options.BatchSize = 1000); Entity Framework ExtensionsEntity Framework ClassicBulk OperationsDapper Plus

Runtime Evaluation Eval.Execute("x + y", new {x = 1, y = 2}); // return 3 C# Eval FunctionSQL Eval Function

JonathanMagnan avatar Oct 24 '20 17:10 JonathanMagnan

@JonathanMagnan Let me clarify.

All instance methods are handled by Dynamic LINQ, as are their arguments. You can put an arbitrary expression as an argument to any instance method and it will be translated to the corresponding expression and query. Like so:

public class Person {
    public string Name { get; set; }
    public string TestMethod(string s) => "";
}

var selector = "TestMethod(FirstName + \"ABCD\")";
var prm = Parameter(typeof(Person));
var parser = new ExpressionParser(new[] { prm }, selector, new object[] { }, ParsingConfig.Default);
var expr = parser.Parse(null);

The LINQ methods (e.g. Select, Where, Any etc.) are different, because they are extension methods, and thus static and not instance methods. Since their types are not accessible by default, they cannot be used within Dynamic LINQ expressions. However, Dynamic LINQ special cases theses static extension methods, because they are commonly used within querying expressions.

But ContainsKey is an instance method, and supported just like all other instance methods which return an accessible type (in this case, bool). It therefore doesn't belong in the list of "static extension methods which Dynamic LINQ has to handle specially".

If you want me to write a PR just to remove ContainsKey from the list, I will do so.

zspitz avatar Oct 24 '20 20:10 zspitz

It's also telling that the documentation describes the parameter for ContainsKey as selector; this is incorrect. While it's true that ContainsKey can contain an arbitrary expression, as in your example above:

"Orders.ContainsKey(it.City + \"TEST\")"

this is a concatenation of City on the outer parameter with the string literal "TEST". This is different from:

var lst = new List<Person>().AsQueryable();
var qry = lst.Where("Orders.Any(DestinationCity = \"TEST\")");

where the parameter passed to Any is not a single value, but rather an inner lambda, relating to the properties of Order -- DestinationCity.

@JonathanMagnan @StefH Any news/thoughts on this?

zspitz avatar May 10 '21 05:05 zspitz