cs0815
cs0815

Reputation: 17418

combine predicates into expression

I am aiming to use this signature:

IEnumerable<T> SearchFor(Expression<Func<T, bool>> expression);

and would like to AND these 2 predicates:

Func<Employee, bool> isActiveEmployee = e => e.DateFired == null;
Func<Employee, bool> isNewEmployee = e => e.DateHired >= DateTime.Today.AddDays(-90);

into an expression. How can I achieve this please?

PS:

Basically, I am trying to use this. But the line:

var body = (BinaryExpression) expression.Body;

in method GetDynamicQuery taken from here throws an exception:

Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.BinaryExpression'.

Using this approach:

Expression<Func<Employee, bool>> isActiveEmployee = e => e.DateFired == null;
Expression<Func<Employee, bool>> isNewEmployee = e => e.DateHired >= DateTime.Today.AddDays(-90);

Expression<Func<Employee, bool>> combined_expression = e => isActiveEmployee.Invoke(e) && isNewEmployee.Invoke(e);

Upvotes: 2

Views: 2997

Answers (1)

Yacoub Massad
Yacoub Massad

Reputation: 27871

I am assuming that you need a real expression that can be translated to SQL by the many data access frameworks.

One solution is to use LinqKit like this:

Expression<Func<Employee, bool>> isActiveEmployee = e => e.DateFired == null;
Expression<Func<Employee, bool>> isNewEmployee = e => e.DateHired >= DateTime.Today.AddDays(-90);

Expression<Func<Employee, bool>> combined_expression = e => isActiveEmployee.Invoke(e) && isNewEmployee.Invoke(e);

Then you can wrap your IQueryable using the AsExpandable method from LinqKit like this:

var query = context.Employees.AsExpandable().Where(combined_expression);

Or, if you don't want to invoke AsExpandable, you can expand the new expression and then use it like any other expression like this:

Expression<Func<Employee, bool>> combined_expression = e => isActiveEmployee.Invoke(e) && isNewEmployee.Invoke(e);

combined_expression = combined_expression.Expand();

var query = context.Employees.Where(combined_expression);

UPDATE:

For the second example you provided, you can do this:

Expression<Func<Employee, bool>> expression1 = e => e.Guid == new Guid("28D3BCFB-9472-4141-BD88-BE5E7E1230F0");

Expression<Func<Employee, bool>> expression2 = e => e.Guid == new Guid("0F0DBA45-F842-4E46-9ED4-F50B5BCF0509");

Expression<Func<Employee, bool>> combined_expression = e => expression1.Invoke(e) || expression2.Invoke(e);

combined_expression = combined_expression.Expand();

// use combined_expression

Upvotes: 3

Related Questions