Search code examples
c#linqjoinobject-graph

Linq query for filter object graph


I have following entitiy relationships. I want to filter resources by passing Project Id.

Project Class

public class Project : EntityBase
{
    public Project()
    {
        this.Tasks = new HashSet<Task>();
    }
    [Key]
    public Guid GUID { get; set; }
    public virtual ICollection<Task> Tasks { get; set; }
}

Task class

public class Task : IIdentifier
{
    public Task()
    {
        this.Assignments = new HashSet<Assignment>();
    }

    [Key]
    public Guid GUID { get; set; }

    [ForeignKey("Projects")]
    public Guid? ProjectId { get; set; }
    public virtual Project Projects { get; set; }

    public virtual ICollection<Assignment> Assignments { get; set; }
}

Resource class

public class Resource : IIdentifier
{
    public Resource()
    {
        this.Assignments = new HashSet<Assignment>();
    }

     [Key]
    public Guid GUID { get; set; }
    public virtual ICollection<Assignment> Assignments { get; set; }
}

Assignment class

 public class Assignment : IIdentifier
{
    [Key]
    public Guid GUID { get; set; }

    [ForeignKey("Tasks")]
    public Guid TaskId { get; set; }
    public virtual Task Tasks { get; set; }

    [ForeignKey("Resources")]
    public Guid ResourceId { get; set; }
    public virtual Resource Resources { get; set; }
}

Now I want to get all the resources when I pass Project GUID

public IEnumerable<Resource> GetResourcesForViewsByProjectId(Guid ProjectId)
    {

        var x = from t in Uow.Tasks.GetAll().Where(con => con.ProjectId == ProjectId)
                from a in Uow.Assignments.GetAll().Where(c => c.TaskId == t.GUID)
                from r in Uow.Resources.GetAll()
                          .Where(r => r.Assignments.Where(con => con.ResourceId == r.GUID))
                          .DefaultIfEmpty()
               select r;

        return x;
    }

but this is not working. Any suggestions?


Solution

  • You should be able to use the Join method for this. Try this:

    public IEnumerable<Resource> GetResourcesForViewsByProjectId(Guid ProjectId)
    {
        var resources = Uow.Tasks.Join(
                Uow.Assignments,
                task => task.GUID,
                    assignment => assignment.TaskId,
                    (task, assignment) => new
                    {
                        Task = task,
                        Assignment = assignment
                    })
                .Join(Uow.Resources,
                    j => j.Assignment.ResourceId,
                    resource => resource.GUID,
                    (j, resource) => new
                    {
                        Task = j.Task,
                        Assignment = j.Assignment,
                        Resource = resource
                    })
                .Where(j => j.Task.ProjectId == ProjectId)
                .Select(j => j.Resource);
    
        return resources;
    }
    

    For reference, the LINQ Join functionality is described here: https://msdn.microsoft.com/en-us/library/bb669071(v=vs.110).aspx