如何过滤IQueryable <t>的嵌套项?

时间:2017-05-16 15:14:30

标签: c# linq iqueryable

我正在构建一个类型为Expression<Func<Project, bool>>的表达式,它从数据库中返回正确的IQueryable<Project>IQueryable<Project>有一个嵌套的SubProjects集合,我也希望对其进行过滤。它看起来像这样

这可以通过一次调用数据库完成吗?

例如:

Expression<Func<Project, bool>> projectFilter = FilterEnabled();

projectFilter = projectFilter.And(GetProjectsByOrganization());

var projectData = GetProjectsAsQueryable(projectFilter); //returns correct projects

这就是我想做的事情:

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

GetProjectsByOrganization如下

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);
}

如何在过滤器中添加Expression<Func<SubProject, bool>>?如果不是我有什么替代品?

1 个答案:

答案 0 :(得分:10)

您应该能够使用Expression.AndAlso将所有3个表达式合并为一个新表达式。使用Expression.PropertyOrField,您可以将您的项目作为参数传递给您的子项目:

    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);
    }