1

I am having a predicate builder and it is working fine

 var filter = sortKeys.Aggregate(filter, (currentFilter, sortkey) => currentFilter.Or(
                            x => x.Appointments.Any(y => y.RowStatus == Constants.CurrentRowStatus )));

I am now trying to split the conditions which is inside the appointment into another predicate builder so that I can add conditions on the go and reuse the function.

I had tried creating an expression and then using it in the main predicate builder but it is failing

private static Expression<Func<Appointment, bool>> TmpApt(string status)
    {
        var predicate = PredicateBuilder.False<Appointment>();

        predicate = predicate.Or(p => p.RowStatus == status);

        return predicate;
    }

Changed main predicate to use the above expression

var filter = sortKeys.Aggregate(PredicateBuilder.True<Person>(), (current, s) =>
                                current.Or(x => x.Appointments.Any(TmpApt(s))));

It showing an error that

Argument type 'System.Linq.Expressions.Expression<System.Func<Appointment,bool>>' is not assignable to parameter type System.Func<Appointment,bool>

I had even tried LinqKit extension method like Expand but could find a solution.

had also tried Reusable predicate expressions in LINQ, then it is not showing any errors while compiling but when on the application side, it is showing

Unsupported overload used for query operator 'Any'.

Can anyone please help me how to resolve the error or suggest an alternative solution.

Community
  • 1
  • 1
Rocky
  • 139
  • 12

1 Answers1

2

You can use LINQKit to invoke the expression that you have at the location that you want to be using it:

var predicate = TmpApt();
var filter = sortKeys.Aggregate(PredicateBuilder.False<Person>(),
    (current, s) => current.Or(x =>
        x.Appointments.Any(appointment => predicate.Invoke(appointment))))
        .Expand();

Note that you'll need to pull TmpApt out into a variable for LINQKit to successfully evaluate it, due to a bug in its implementation.

Also note that you'll want to initialize the aggregate operation to False, because True OR-ed with anything is true.

Also note that you can simplify the implementation of TmpApt to just the following:

private static Expression<Func<Appointment, bool>> TmpApt()
{
    return p => p.RowStatus == Constants.CurrentRowStatus;
}

There's no need to use a predicate builder to Or it with False here.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Thanks very much... Your solution is working great but I am having a new problem now.. I want to pass parameters into TmpApt(). The parameter values are coming from "s" (which is in the aggregrate). I am not sure how to pass when we declare it as a variable and then invoking it. Is there any workaround for this. I will update the main question also. I am sorry it was my mistake. T. make the question easy I had removed the variable of the method. Thanks very much for your help and for you time. – Rocky Sep 25 '14 at 17:02
  • @Rocky Well The simplest option would be to refactor the invocation of `TmpApt` to the `Aggregate` lambda. It can't be within the lambda that is compiled to an expression, unless you want to first fix the bug in LINQKit, which is certainly possible, but not simple. – Servy Sep 25 '14 at 17:06