17
EmployeeId  Name  ManagerId
------------------------------
1           A     null
2           B     null
3           C     1
4           D     3
5           E     2

just using this table, how can a linq query (using linq to sql) be written to fetch the parent data recursively.

For instance if the Employer Id selected is 4 it should give list of employees with Id: 4, 3, 1

Thanks.

4
  • 4,3,1?? What kind of algorithm you saying? :) What will happens If I select 5? Commented Nov 1, 2010 at 19:02
  • @Serkan: That should give a list of employee(s) with id: 5, 2 Commented Nov 1, 2010 at 19:05
  • I still cant understand you. 2 is managerId? If yes, as I understand. You want selected EmployeeId and this EmployeeId's managerId as EmployeeId ? Commented Nov 1, 2010 at 19:08
  • @Serkan: It has to recursively fetch the parent data. So if 4 is the selected employee id, it will go and select 3 (4's manager id), and then go and select 1 (3's manager id). Since 1 does not have a manager id it will stop and return 4,3, and 1. Commented Nov 1, 2010 at 19:11

4 Answers 4

9

This .AsHierarchy() extension method may be useful: link. However, this only works by providing an easy way to throw your results into linked objects. In order to do that, it'll just get all the records and run its own local recursive query.

If you're looking for a LINQ query that will directly translate to a recursive SQL query via LINQ to SQL, you won't find it. For the best performance, a CTE in a stored procedure is probably what you're looking for. If you have a really simple page that needs to load the whole tree anyway, the AsHierarchy method would probably fit your needs.

Sign up to request clarification or add additional context in comments.

Comments

2

I'm not sure if this is exactly what you want, but here is one recursive method that uses some linq that makes sure not to enter an infinite loop:

    public static IEnumerable<Employee> GetTreeForEmployeeNumber(this IEnumerable<Employee> source, int startingId) {
        var result = source.Where(x => x.EmployeeId == startingId).FirstOrDefault();
        if (result != null) {
            var resultAsE = new [] { result };
            if (!result.ManagerId.HasValue)
                return resultAsE;
            return resultAsE.Union(source.Except(resultAsE).GetTreeForEmployeeNumber(result.ManagerId.Value));
        }
        return new Employee [] { };
    }

If you have linqpad installed you can test this with the following script:

void Main()
{
    var lst = new [] {
        new Extensions.Employee{ EmployeeId = 1, Name = "A", ManagerId = null }, 
        new Extensions.Employee{ EmployeeId = 2, Name = "B", ManagerId = null }, 
        new Extensions.Employee{ EmployeeId = 3, Name = "C", ManagerId = 1 }, 
        new Extensions.Employee{ EmployeeId = 4, Name = "D", ManagerId = 3 }, 
        new Extensions.Employee{ EmployeeId = 5, Name = "E", ManagerId = 2 }
    };

    lst.GetTreeForEmployeeNumber(4).Dump();
}

public static class Extensions {

    public class Employee {
        public int EmployeeId { get; set; }
        public string Name { get; set; }
        public int? ManagerId { get; set; }
    }

    public static IEnumerable<Employee> GetTreeForEmployeeNumber(this IEnumerable<Employee> source, int startingId) {
        var result = source.Where(x => x.EmployeeId == startingId).FirstOrDefault();
        if (result != null) {
            var resultAsE = new [] { result };
            if (!result.ManagerId.HasValue)
                return resultAsE;
            return resultAsE.Union(source.Except(resultAsE).GetTreeForEmployeeNumber(result.ManagerId.Value));
        }
        return new Employee [] { };
    }
}

Comments

0

You could do something like

    int id = 5;
    do
    {
        employee= employeedata.FirstOrDefault(e => e.EmployeeId == id);

    } while (employee != null && (id = employee.ManagerId) != 0);

but it's a rather dangerous thing to do since it can get stuck in an infinite loop. As far as I know there's no way to make a recursive query directly unless you write a stored procedure.

2 Comments

Yeah I know it can be done by writing CTE within a stored proc. I wanted to see if there is a way to achieve that directly through linq to sql expression. Seems like answers are gearing towards "NO".
hmm :) I didnt hear an expression which can make recursive. I thought you asking how to make programmaticaly :)
0
var managedEmployees = ctx.Employess.Where(x => x.ManagerId = 4).AsEnumerable()

If you want the whole tree at once, the solution is more complex. In SQL its best done with an CTE, I don't know if EF can handle this using linq- more likely an iterative solution would be used.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.