2017-05-16 2 views
8

Je suis en train de construire une expression de type Expression<Func<Project, bool>> qui renvoie le bon IQueryable<Project> de la base de données. IQueryable<Project> a une collection imbriquée de SubProjects que je voudrais filtrer aussi bien. Cela ressemble à ceci:Comment puis-je filtrer les éléments imbriqués de IQueryable <T>?

Est-ce que cela peut être fait avec un appel à la base de données?

Par exemple:

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

projectFilter = projectFilter.And(GetProjectsByOrganization()); 

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

C'est ce que je voudrais faire:

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 

Le GetProjectsByOrganization se présente comme suit

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

Comment puis-je ajouter un Expression<Func<SubProject, bool>> à la filtre? Si non quelles alternatives ai-je?

Répondre

10

Vous devriez pouvoir utiliser Expression.AndAlso pour combiner les 3 Expressions à une nouvelle. Avec Expression.PropertyOrField vous pouvez passer votre place votre projet Sous-projet en tant que paramètre:

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

Je ne pense pas que cela fonctionnera avec EntityFramework –

+0

@ Johnny5 Je n'ai pas encore essayé mais pourquoi? Y a-t-il un autre moyen de le faire? –