Search code examples
asp.net-mvclinqasp.net-corelinq-to-sqllinq-to-entities

Linq Multiple Orderby Query in one Listing with multiple conditions


var result = await projectRepo.GetPagedListAsync(x => new ProjectApiModel
            {
                ProjectId = x.Id,
                ProjectKey = x.ProjectKey,
                ProjectName = x.ProjectName,
                ProjectStatus = x.ProjectStatus,
                Tasks = x.Tasks.Where(z => /*z.AgentId == referenceId &&*/ z.Status == true && (z.TaskStatus == null || z.TaskStatus.StatusName != "Closed")).Select(y => new TaskApiModel
                {
                    TaskId = y.Id,
                    TaskName = y.TaskName,
                    ProjectId = y.ProjectId,
                    TaskTypeName = y.TaskType.TypeName,
                    TaskPriority = y.TaskPriorityId == null ? null : new PriorityModel { Name = y.TaskPriority.Name, Color = y.TaskPriority.Color, Id = y.TaskPriority.Id, Scale = y.TaskPriority.Scale },
                    TaskStatus = y.TaskStatusId == null ? null : new StatusModel { StatusName = y.TaskStatus.StatusName, Color = y.TaskStatus.Color, Scale = y.TaskStatus.Scale, StatusId = y.TaskStatus.Id, Status = y.TaskStatus.Status },
                    Deadline=y.EndDateUTC
                }).ToList()
            },orderBy: orders => orders.OrderBy(o => o.ProjectName));

This is what I am using for sorting my project list with the project name and its going well. Now I want to change the orderby by conditions as see below.

  1. First want to show all the projects which contain TaskPriority as "urgent" In any one of the tasks(Every project has tasklist).
  2. rest all projects want to show an ascending order.
  3. If any project name starting with numeric should be in last.

I tried the code

orderBy: orders => orders.OrderBy(o => o.Tasks.Any(s=>s.TaskPriority.Name.ToLower()== "urgent")).ThenBy(i=>i.ProjectName));

Solution

  • I hope I understood your question correctly. The reason why your query didn't work was when ordering booleans, False is ordered first.

    What you need to do is Order By Descending in the first condition.

    orders.OrderByDescending(o => o.Tasks.Any(s=>s.TaskPriority.Name.ToLower()== "urgent"))
           .ThenBy(i=>i.ProjectName));
    

    For Example, mock your scenario with simpler version of your classes

    public class Project
    {
        public long ProjectId{get;set;}
        public string ProjectName{get;set;}
        public IEnumerable<ProjectTask> Task{get;set;}
    }
    
    public class ProjectTask
    {
        public long TaskId{get;set;}
        public string TaskPriority{get;set;}
    }
    

    Client Code

    var project1 = new Project
    {
        ProjectId=1,
        ProjectName = "abc",
        Task = new []
        {
            new ProjectTask{TaskId=1,TaskPriority="urgent"},
            new ProjectTask{TaskId=1,TaskPriority="moderate"},
        }
    };
    
    var project2 = new Project
    {
        ProjectId=2,
        ProjectName = "aaa",
        Task = new []
        {
            new ProjectTask{TaskId=1,TaskPriority="moderate"},
            new ProjectTask{TaskId=1,TaskPriority="moderate"},
        }
    };
    
    
    var project3 = new Project
    {
        ProjectId=2,
        ProjectName = "abb",
        Task = Enumerable.Empty<ProjectTask>()
    };
    
    var project4 = new Project
    {
        ProjectId=2,
        ProjectName = "abaa",
        Task = new []
        {
            new ProjectTask{TaskId=1,TaskPriority="moderate"},
            new ProjectTask{TaskId=1,TaskPriority="moderate"},
        }
    };
    
    var listOfProjects = new [] {project1,project2,project3,project4};
    
    var r = listOfProjects.OrderByDescending(o => o.Task.Any(s=>s.TaskPriority.ToLower()== "urgent"))
                          .ThenBy(i=>i.ProjectName);
    

    Sample Output

    enter image description here