【问题标题】:Linq to Sql - Hierarchical Query to Find AncestorsLinq to Sql - 查找祖先的分层查询
【发布时间】:2008-10-25 15:29:16
【问题描述】:

给定一个 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;
}

【问题讨论】:

    标签: .net linq-to-sql hierarchy


    【解决方案1】:

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

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

    我会选择一条不同的路径并创建一个存储过程来为我执行此操作并返回整个Employee 对象集。由于您在返回对象(处理上下文)之前断开它们的连接,因此您可以简单地从存储过程的结果集中创建新对象。

    【讨论】:

      【解决方案2】:

      避免加载整个 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 来支持服务器端执行)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        • 2012-11-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多