Home > OS >  How to get the list of employees and their reporting level recursively using LINQ
How to get the list of employees and their reporting level recursively using LINQ

Time:05-20

I have a table for list of employees with their supervisors.

| UserID | SupervisorUserId |
|--------|------------------|
| 10     | null             |
| 1      | 10               |
| 2      | 1                |
| 3      | 1                |
| 4      | 3                |
| 5      | 10               |
| 6      | 5                |
| 7      | 6                |
| 8      | 6                |
| 9      | 8                |

Here's a diagram for visualisation:

Employee hierarchy chart

And here's what I have right now:

public JsonResult GetEmployeesWithReportingLevel()
{
    try
    {

        var getEmployees = GetEmployees().ToList();

        var employeeList = (from e in getEmployees
                            where e.IsDeleted != true
                            select new ReportingLineList
                            {
                                UserId = e.UserId,
                                SupervisorId = e.SupervisorId 
                            }).ToList();

        var reportingLevel = (from emp in employeeList
                                select new 
                                {
                                    UserId = emp.UserId,
                                    ReportingLevel = GetReportingLevel(employeeList, emp.UserId, 0)
                                }).ToList();

        return new JsonResult(reportingLevel);
    }
    catch
    {
        throw;
    }
}
private int GetReportingLevel(IEnumerable<ReportingLineList> employeeList, Guid UserId, int reportingLevel)
{
    try
    {
        var reportingEmployees = (from emp in employeeList
                                        where emp.SupervisorId == UserId
                                        select new 
                                        {
                                            UserId = emp.UserId
                                        }).ToList();

        foreach (var emp in reportingEmployees)
        {
            if (emp.UserId != null)
            {
                return GetReportingLevel(employeeList, (Guid)emp.UserId, reportingLevel   1);
            }
        }

        return reportingLevel;
    }
    catch
    {
        throw;
    }
}

My expected result should be:

| UserId | Reporting level |
|--------|-----------------|
| 2      | 0               |
| 4      | 0               |
| 7      | 0               |
| 9      | 0               |
| 3      | 1               |
| 8      | 1               |
| 1      | 2               |
| 6      | 3               |
| 5      | 3               |
| 10     | 4               |

With my current result, it seems like it is just iterating with the first employee that my code will get.

Here's the result that I'm getting.

| UserId | Reporting level |
|--------|-----------------|
| 2      | 0               |
| 4      | 0               |
| 7      | 0               |
| 9      | 0               |
| 3      | 1               |
| 8      | 1               |
| 1      | 1               |
| 6      | 1               |
| 5      | 2               |
| 10     | 3               |

CodePudding user response:

Firstly, you say you expect UserId 6 to have a reporting level of 3, but if I understand the problem, then both data and diagram would suggest it should be 2.

If that is correct, then the problem is with your GetReportingLevel method. You need to keep a track of both the currentLevel and the MaximumReportingLevel. Every time you descend a level you need to increase currentLevel and then decrease it again when you have finished with that level and this needs to be independent of MaximumReportingLevel, which should only change if it finds a deeper level than before.

For example, when you are processing Employee 10 you recursively process Employee 1 on level 1 and then Employee 2 on Level 2, but then you need to go back to Level 1 to process Employee 3 while not losing the fact that your maximum level was 2.

Your code also does not compile for me, e.g. is UserID an int or a Guid etc, but I think the following should work (I have deliberately tried to leave most of your code as is)

private int GetReportingLevel(IEnumerable<ReportingLineList> employeeList, Guid UserId, 
                              int MaxReportingLevel = 0, int CurrentLevel = 0)
{
    try
    {
        var reportingEmployees = (from emp in employeeList
                                  where emp.SupervisorId == UserId
                                  select new
                                  {
                                      UserId = emp.UserId
                                  }).ToList();

        CurrentLevel  ;
        foreach (var emp in reportingEmployees)
        {
            if (emp.UserId != null)
            {
                int newLevel = GetReportingLevel(employeeList, (Guid)emp.UserId,
                                                 MaxReportingLevel , CurrentLevel);
            
                MaxReportingLevel = Math.Max(currentLevel, newLevel);
            }
        }
        CurrentLevel--;

        return MaxReportingLevel;
    }
    catch
    {
        throw;
    }
}

CodePudding user response:

So I am kinda new also, but it seems like your problem can just be fixed by adding an .OrderBy() if I'm not mistaken.

Here is a link to check it out: MSDN Enumerable.OrderBy Method

  • Related