5

I'm getting the error Unable to cast object of type 'System.Linq.Expressions.FieldExpression' to type 'System.Linq.Expressions.LambdaExpression' when running the below code.

The intent of this code is to allow me to filter records (Entity Framework Code First / Linq to SQL) for those containing certain strings.

NB: I'm using the third party library LinqKit: http://www.albahari.com/nutshell/predicatebuilder.aspx

FilterHelper<Country> helper = new FilterHelper<Country>();
helper.AddContains(searchAlpha2, c => c.Alpha2);
helper.AddContains(searchAlpha3, c => c.Alpha3);
helper.AddContains(searchName, c => c.Name);

IQueryable<Country> countries = db.Countries.AsExpandable().Where(helper.Predicate);

...

public class FilterHelper<T>
{
    public delegate string GetColumn<T>(T item);

    private Expression<Func<T,bool>> predicate; 

    public FilterHelper()
    {
        this.predicate = PredicateBuilder.True<T>();
    }
    public void AddContains(string searchText, GetColumn<T> getColumn)
    {
        if (!string.IsNullOrWhiteSpace(searchText))
            predicate = predicate.And(c => getColumn(c) != null ? getColumn(c).Contains(searchText) : false);
    }  
    public Expression<Func<T,bool>> Predicate
    {
        get { return this.predicate; }
    }

}

Any suggestions on how I could rewrite this to avoid the above error?

NB: code also on CodeReview as my original question related to refactoring. https://codereview.stackexchange.com/questions/54888/refactor-c-linq-code-to-reduce-duplication

Community
  • 1
  • 1
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
  • Are you using the DLL from the site you linked to, or from NuGet? I think this is something that has been fixed, so try the NuGet version if you aren't already. – Mark Jun 22 '14 at 01:53
  • Thanks Mark; I was using the one from the site; replacing with NuGet version now... – JohnLBevan Jun 22 '14 at 02:00
  • Sadly still getting the same (v1.1.1 from nuget / related page: https://www.nuget.org/packages/LinqKit/) – JohnLBevan Jun 22 '14 at 02:18
  • 1
    Same error, different cause then. I suspect that it's related to the getColumn parameter, which seems like it should be something like `Expression>` so that the predicate can use the property, instead of the value, but I'm just starting to learn about expressions and can't be much help there. – Mark Jun 23 '14 at 00:56
  • @JohnLBevan Can you provide an example of how you resolved your issue using Gordon's answer? As hard as I try, I can't seem to make a type of `Expression>` work in place of your `getColumn` delegate. – kay Dec 21 '16 at 19:34
  • 3
    I think I got it! Looks like I needed to use Invoke. So if `getColumn` is of type `Expression>`, then `predicate = predicate.And(c => getColumn.Invoke(c) != null ? ...);` – kay Dec 21 '16 at 20:27
  • Nice one @karol; thanks for sharing; I was trying to recall what code I'd used this in to dig out an answer for you, but you beat me to it :). – JohnLBevan Dec 22 '16 at 08:38

1 Answers1

1

A FieldExpression is not a LambdaExpression. You can make one as the body of an expression. In the debugger you can try the following to explore the structure of a LambdaExpression:

Expression<Func<U,T>> f = t => t.FieldName;

then in the debugger, look at f, which is of type LambdaExpression, and the Body of LambdaExpression which is Field Expression.

Gordon
  • 3,012
  • 2
  • 26
  • 35