Search code examples
vb.netlinqentity-frameworklinqkit

Unable to cast FieldExpression to LambdaExpression


I've written the following function to check an added/modified record for overlapping time periods in the database:

<Extension> Function ClashRecords(Of T)(Query As IQueryable(Of T), Record As T, _
        KeySelector As Expression(Of Func(Of T, Integer)), 
        FromSelector As Expression(Of Func(Of T, DateTime)), 
        TillSelector As Expression(Of Func(Of T, DateTime))) As IQueryable(Of T)
    Dim key = KeySelector.Invoke(Record)
    Dim fromDate = FromSelector.Invoke(Record)
    Dim tillDate = TillSelector.Invoke(Record)
    Dim criteriaExpr As Expression(Of Func(Of T, Boolean)) = Function(x) KeySelector.Invoke(x) = key And FromSelector.Invoke(x) <= tillDate And TillSelector.Invoke(x) >= fromDate
    Return Query.AsExpandable.Where(criteriaExpr.Expand)
End Function

When calling the function as follows:

Dim de As New DataEntities()
Dim w=New Work With {.WorkerID=-1,.FromDate=New DateTime(2014,3,20,7,0,0),.TillDate=New DateTime(2014,3,20,8,30,0)}
Dim clashing = de.Works.ClashRecords(w,Function(x) x.ActivistID, Function(x) x.FromDate, Function(x) x.TillDate)

I get the following error:

InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.FieldExpression' to type 'System.Linq.Expressions.LambdaExpression'.

I don't see that I am using any field expressions -- ActivistID, FromDate, TillDate are all properties.

I am using EF5 and generated POCO classes.

How can I resolve this?

Update

If I enter criteriaExpr.Expand in the Watch window, I don't get an exception. However, if I enter criteriaExpr.Expand.Compile I get the same exception.


Solution

  • See: How do closures work behind the scenes? (C#)

    If a variable from the outer scope is accessed from an inner function, the compiler creates a hidden type to own the variables as fields. Your criteriaExpr accesses the outer function parameters, so it contains FieldExpressions.

    I took a quick look at LinqKit's source code (which you seem to be using judging by the Expand and Compile), and it appears that it doesn't support Invoke on a FieldExpression.