jimmyjambles
jimmyjambles

Reputation: 1670

Using Expression<Func<>> in Where clause with parameters

I have the following query using linq method syntax

IEnumerable<PageElement> elements_test = ObjectContext.PageElements
            .Where(_dateDebutCheck).Where(_dateFinCheck)
            .Where(_activeLanguageCheck(language));

private readonly Expression<Func<PageElement, bool>> _dateDebutCheck = pe => pe.DateDebut.HasValue && pe.DateDebut.Value <= DateTime.Now;
private readonly Expression<Func<PageElement, bool>> _dateFinCheck = pe => !pe.DateFin.HasValue || pe.DateFin.Value > DateTime.Now;

private readonly Expression<Func<PageElement, byte, bool>> _activeLanguageCheck =
        (pe, lang) => pe.PageElementLanguages.Where(y => y.Active).Select(y => y.LanguageId).Contains(lang);

The syntax appears to be correct for the first 2 expressions that do not take parameters, how can I invoke the third expression with the language parameter in my Where clause?

Upvotes: 2

Views: 4214

Answers (2)

Cyril Gandon
Cyril Gandon

Reputation: 17048

The Where in LINQ to entities takes an Expression<Func<TSource, Boolean>> which is not what you have.

So your question is instead : How to convert Expression<Func<PageElement, byte, bool>> to Expression<Func<PageElement, bool>>

Here is a simple helper function to do that:

public static Expression<Func<T1, TResult>> ToSimpleFunc<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> f, T2 value)
{
    var invokeExpression = Expression.Invoke(f, f.Parameters[0], Expression.Constant(value));
    return Expression.Lambda<Func<T1, TResult>>(invokeExpression, f.Parameters[0]);
}

Call it this way:

IEnumerable<PageElement> elements_test = ObjectContext.PageElements
        .Where(_dateDebutCheck).Where(_dateFinCheck)
        .Where(ToSimpleFunc(_activeLanguageCheck, language));

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1062600

Rather than having a lambda with an extra parameter, you can have a method that creates the lambda capturing the desired value:

private Expression<Func<PageElement, bool>> ActiveLanguageCheck(byte lang) {
    return pe => pe.PageElementLanguages.Where(
                    y => y.Active).Select(y => y.LanguageId).Contains(lang);
}

Then just:

.Where(ActiveLanguageCheck(language))

Upvotes: 7

Related Questions