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

Tra*_*ain 8 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
Run Code Online (Sandbox Code Playgroud)

这就是我想做的事情:

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
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

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

小智 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);
    }
Run Code Online (Sandbox Code Playgroud)