I'm trying to code this LINQ query with expression trees:
Result = Result.Where(Function(Row) Convert.ToInt32(Row(2)) <= 10)
Result
is declared as Dim Result As IEnumerable(Of Object())
.
I have this code so far:
Dim queryiabledata As IQueryable(Of Object()) = Result.AsQueryable
Dim pe As ParameterExpression = Expression.Parameter(GetType(String), "Row(2)")
Dim left As expression = Expression.Call(pe, GetType(String).GetMethod("Convert.ToInt32", System.Type.EmptyTypes))
Dim right As Expression = Expression.Constant(10)
Dim e1 As Expression = Expression.LessThanOrEqual(left, right)
Dim predicatebody As Expression = e1
Dim wherecallexpression As MethodCallExpression = Expression.Call(
GetType(Queryable), "Where", New Type() {queryiabledata.ElementType}, queryiabledata.Expression,
Expression.Lambda(Of Func(Of Object(), Boolean))(predicatebody, New ParameterExpression() {pe}))
Result = queryiabledata.Provider.CreateQuery(Of Object())(wherecallexpression)
But if I run the query, I get an ArgumentNullException (Value cannot be null. Parameter name: method) at Expression.Call
.
I tried to change "Convert.ToInt32"
to "Value"
, but I got the same error.
How can I fix it?
Are the another code lines right to get the desired result?
I'm more used to C#, though I do VB.NET occasionally. Reflection in VB.NET is downright ugly. Getting the Where
method is a bit of a hack. Here's the code:
shortForm
and longForm
should be identical.
Dim result As IEnumerable(Of Object()) = New List(Of Object())()
Dim queryiabledata As IQueryable(Of Object()) = result.AsQueryable()
Dim shortForm As Expression = queryiabledata.Where(Function(Row) Convert.ToInt32(Row(2)) <= 10).Expression
Dim whereMethod = GetType(Queryable).GetMethods(BindingFlags.Public Or BindingFlags.Static).
First(Function(m) m.Name = "Where").
MakeGenericMethod(GetType(Object()))
Dim convertMethod = GetType(System.Convert).GetMethod("ToInt32", New Type() {GetType(Object)})
Dim rowParameter = Expression.Parameter(GetType(Object()), "Row")
Dim longform As Expression =
Expression.Call(
whereMethod,
queryiabledata.Expression,
Expression.Lambda(
Expression.LessThanOrEqual(
Expression.Call(
convertMethod,
Expression.ArrayAccess(
rowParameter,
Expression.Constant(2)
)
),
Expression.Constant(10)
),
rowParameter
)
)
result = queryiabledata.Provider.CreateQuery(longform)