Linq to Sql - Hierarchical Query to Find Ancestors

谁说胖子不能爱 提交于 2019-12-05 01:32:58

问题


Given an EmployeeId, how can I construct a Linq to Sql query to find all of the ancestors of the employee? Each EmployeeId has an associated SupervisorId (see below).

For example, a query of the ancestors for EmployeeId 6 (Frank Black) should return Jane Doe, Bob Smith, Joe Bloggs, and Head Honcho.

If necessary, I can cache the list of all employees to improve performance.

UPDATE:

I've created the following crude method to accomplish the task. It traverses the employee.Supervisor relationship all the way to the root node. However, this will issue one database call for each employee. Anyone have a more succinct or more performant method? Thanks.

private List<Employee> GetAncestors(int EmployeeId)
{
    List<Employee> emps = new List<Employee>();
    using (L2STestDataContext dc = new L2STestDataContext())
    {
        Employee emp = dc.Employees.FirstOrDefault(p => p.EmployeeId == EmployeeId);
        if (emp != null)
        {
            while (emp.Supervisor != null)
            {
                emps.Add(emp.Supervisor);
                emp = emp.Supervisor;
            }
        }
    }
    return emps;
}

回答1:


First of all, you're welcome to use the hierarchical queries in my LINQ Extension Methods project. I think may help simplify your code.

The problem here is that this will create a database call for each node in the hierarchy. In the case of your example, you will have 5 round-trips to the database.

I'd go a different path and create a stored-procedure to do that for me and return the whole set of Employee objects. Since you're disconnecting the objects before returning them (disposing of the context), you could simply create new object from the stored procedure's result-set.




回答2:


A simple solution that avoids loading the whole Employee table (but has a limited traversal depth) is...

var emps = dc.Employees.Where(e => (e.EmployeeId == EmployeeId) ||
                                   (e.SupervisorId == EmployeeId) ||
                                   (e.Supervisor.SupervisorId == EmployeeId) ||
                                   (e.Supervisor.Supervisor.SupervisorId == EmployeeId) ||
                                   ...);

Ultimately, you should use a common table expression to flatten the hierarchy, but LINQ to SQL doesn't currently support this. You could look into writing your own extension method (like the one in Omer's library but using IQueryable instead of IEnumerable to support server-side execution).



来源:https://stackoverflow.com/questions/236575/linq-to-sql-hierarchical-query-to-find-ancestors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!