Linq to Sql - 查找祖先的分层查询

时间:2008-10-25 15:29:16

标签: .net linq-to-sql hierarchy

给定一个EmployeeId,我如何构建一个Linq to Sql查询来查找该员工的所有祖先?每个EmployeeId都有一个相关的SupervisorId(见下文)。

例如,对EmployeeId 6(Frank Black)的祖先的查询应该返回Jane Doe,Bob Smith,Joe Bloggs和Head Honcho。

如有必要,我可以缓存所有员工的名单以提高绩效。

更新

我已经创建了以下原始方法来完成任务。它遍历employee.Supervisor关系一直到根节点。但是,这将为每个员工发出一个数据库调用。任何人都有更简洁或更高效的方法?感谢。

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;
}

2 个答案:

答案 0 :(得分:1)

首先,欢迎您在LINQ Extension Methods project中使用分层查询。我认为可能有助于简化您的代码。

这里的问题是,这将为层次结构中的每个节点创建一个数据库调用。在您的示例中,您将有5次往返数据库。

我将使用不同的路径并创建一个存储过程来为我执行此操作并返回整组Employee个对象。由于在返回对象之前断开对象(处理上下文),您只需从存储过程的结果集中创建新对象。

答案 1 :(得分:1)

避免加载整个Employee表(但遍历深度有限)的简单解决方案是......

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

最终,您应该使用common table expression来展平层次结构,但LINQ to SQL目前不支持此功能。你可以考虑编写自己的扩展方法(比如Omer库中的扩展方法,但使用IQueryable而不是IEnumerable来支持服务器端执行)。