There is no "Contains" method in the type "System.Data.Linq.DataQuery`1 [System.Object]"

I am trying to build contains an expression.

private Expression<Func<T, bool>> Contains<T>(string property, IEnumerable<dynamic> values, T item) { ParameterExpression pe = Expression.Parameter(item.GetType(), "c"); Expression columnNameProperty = Expression.Property(pe, property); var someValueContain = Expression.Constant(values, values.GetType()); var convertExpression = Expression.Convert(columnNameProperty, typeof(Guid)); Expression expression = Expression.Call(someValueContain, "Contains", new Type[] { }, convertExpression); return Expression.Lambda<Func<T, bool>>(expression, pe); } 

at runtime, I got this exception.

"No method 'Contains' exists by type 'System.Data.Linq.DataQuery`1 [System.Object]'”.

the soul should have indicated a parameter value in the list

 private Expression<Func<T, bool>> Contains<T>(string property, IEnumerable<dynamic> values, T item) { ParameterExpression pe = Expression.Parameter(item.GetType(), "c"); Expression columnNameProperty = Expression.Property(pe, property); Guidvalues = values.Cast<Guid>().ToList(); var someValueContain = Expression.Constant(Guidvalues, Guidvalues.GetType()); var convertExpression = Expression.Convert(columnNameProperty, typeof(Guid)); Expression expression = Expression.Call(someValueContain, "Contains", new Type[] { }, convertExpression); return Expression.Lambda<Func<T, bool>>(expression, pe); } 

the problem is that the list of values ​​is greater than 10000, so the performance is low, and I got this exception

"The incoming request has too many parameters. The server supports a maximum of 2100 parameters. Reduce the number of parameters and send the request.

Is there a way to build dynamically a lambda expression that generates such a query

 select * from x where id in (select id from y) 
+6
source share
1 answer

It's just syntactic sugar that gets better than you :)

The problem is that Contains really not a method on DataQuery<T> - it is a static method in System.Linq.Queryable . The C # compiler handles this for you using extension methods, but it's just a C # compiler - this is not a feature of IL, it is a feature of C #. Therefore, when you manipulate expression trees or emit raw IL, you must handle this yourself:

 private Expression<Func<T, bool>> Contains<T, V> (string property, IQueryable<V> values, T item) { ParameterExpression pe = Expression.Parameter(item.GetType(), "c"); Expression columnNameProperty = Expression.Property(pe, property); var someValueContain = Expression.Constant(values, values.GetType()); var convertExpression = Expression.Convert(columnNameProperty, typeof(V)); Expression expression = Expression.Call ( ( ((Expression<Func<bool>>) (() => Queryable.Contains(default(IQueryable<V>), default(V))) ) .Body as MethodCallExpression).Method, someValueContain, convertExpression ); return Expression.Lambda<Func<T, bool>>(expression, pe); } 

I would avoid using dynamic in LINQ queries, since you are using it, this is no better than having an IEnumerable<object> , and if you want it to always be Guid anyway, just do it generic :)

This method assumes that any type of column can be converted to the type of elements you enumerate, of course, of course, but it will work for any type, not just Guid .

However, this will not solve the second problem that you have - it is quite explicit. The passage you listed has too many items to pass. If your LINQ provider does not have a better way of passing values, you will have to resort to splitting the query into several separate queries, each of which, for example, 1000 elements, and then merging the results. Unless, of course, my guess is correct, and the values you pass are actually also a request - in this case, the code should work fine.

EDIT:

The best way to find the right MethodInfo is with a set of methods like this:

 public static MethodInfo Method<TR>(Expression<Func<TR>> expression) { return (expression.Body as MethodCallExpression).Method; } public static MethodInfo Method<T1, TR>(Expression<Func<T1, TR>> expression) { return (expression.Body as MethodCallExpression).Method; } 

(autogenerated in the same way as actual delegates Func<...> )

This makes it easier to obtain information about this method:

 Method((IQueryable<T> queryable, T item) => queryable.Contains(item)) 

Or, conversely, (so as not to create all possible overloads):

 Method(() => default(IQueryable<T>).Contains(default(T))) 
+3
source

All Articles