c# - No method 'Contains' exists on type 'System.Data.Linq.DataQuery`1[System.Object]' -
i trying build contains 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 run time got exception.
"no method 'contains' exists on type 'system.data.linq.dataquery`1[system.object]'."
the soultion cast values parameter 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 values list more 10000 performance low , got exception
"the incoming request has many parameters. server supports maximum of 2100 parameters. reduce number of parameters , resend request."
i there way build dynamically lambda expression generate query
select * x id in (select id y)
this syntactic sugar getting better of :)
the problem contains
indeed not method on dataquery<t>
- it's static method in system.linq.queryable
. c# compiler handles via extension methods, that's c# compiler - it's not feature of il, it's feature of c#. when you're manipulating expression trees or emitting raw il, have handle 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 methodcallexpression).method, somevaluecontain, convertexpression ); return expression.lambda<func<t, bool>>(expression, pe); }
i'd avoid using dynamic
in linq queries - way you're using it, it's no better having ienumerable<object>
, , if want guid
anyway, make generic :)
this method assumes whatever type of column convertible type of items in enumerable you're passing, of course, work type, not guid
.
however, not solve second problem have - it's quite explicit. enumerable you're passing has way many items pass. unless linq provider has better way of passing values, you'll have resort splitting query multiple separate queries, each e.g. 1000 items, , joining results together. unless of course, guess right, , values
you're passing in fact queryable - in case, code should work fine.
edit:
the best way i've found of getting proper methodinfo
set of methods this:
public static methodinfo method<tr>(expression<func<tr>> expression) { return (expression.body methodcallexpression).method; } public static methodinfo method<t1, tr>(expression<func<t1, tr>> expression) { return (expression.body methodcallexpression).method; }
(autogenerated same way actual func<...>
delegates are)
this allows simplifying getting method info this:
method((iqueryable<t> queryable, t item) => queryable.contains(item))
or alternatively (to avoid having generate possible overloads):
method(() => default(iqueryable<t>).contains(default(t)))
Comments
Post a Comment