I am building an expression of type Expression<Func<Project, bool>>
which returns the correct IQueryable<Project>
from the database. IQueryable<Project>
has a nested collection of SubProjects
that I would like to filter as well. It looks something like this
Can this be done with one call to the database?
For example:
Expression<Func<Project, bool>> projectFilter = FilterEnabled();
projectFilter = projectFilter.And(GetProjectsByOrganization());
var projectData = GetProjectsAsQueryable(projectFilter); //returns correct projects
This is what I would like to do:
Expression<Func<Project, bool>> projectFilter = FilterEnabled();
projectFilter = projectFilter.And(GetProjectsByOrganization())
.And(GetSubProjectsByStartDate());
var projectData = GetProjectsAsQueryable(projectFilter); //returns correct projects and the filtered sub projects by start date
The GetProjectsByOrganization
is as follows
public Expression<Func<Project, bool>> GetProjectByOrganization()
{
var organizationIDs = new List<Guid>();
if (FilterCriteria.OrganiazaitonId != null)
organizationIDs = OrganizationRepository.GetParentAndChildrenOrganizationIds(FilterCriteria.OrganiazaitonId.Value).ToList();
//...
return prj => FilterCriteria.OrganiazaitonId == null || organizationIDs.Contains(prj.OrganizationID.Value);
}
How can I add an Expression<Func<SubProject, bool>>
to the filter? If not what alternatives do I have?
You should be able to use Expression.AndAlso
to combine all 3 Expressions to a new one. With Expression.PropertyOrField
you can pass your SubProject instead your Project as Parameter:
static Expression<Func<Project, bool>> CombineFilterExpression(
Expression<Func<Project, bool>> firstProjectFilter,
Expression<Func<Project, bool>> secondProjectFilter,
Expression<Func<SubProject, bool>> subProjectFilter
)
{
//Create Project Parameter
var param = Expression.Parameter(typeof(Project));
//Create && Expression
var body = Expression.AndAlso(
Expression.Invoke(firstProjectFilter, param),
Expression.AndAlso( //Create second && Expression
Expression.Invoke(secondProjectFilter, param),
//Pass SubProject instead of Project
Expression.Invoke(subProjectFilter, Expression.PropertyOrField(param, nameof(Project.SubProject)))
)
);
//Make Lambda with Project parameter
return Expression.Lambda<Func<Project, bool>>(body, param);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With