2008-10-25 80 views
4

給定一個EmployeeId,我該如何構建一個Linq to Sql查詢來查找所有員工的祖先?每個EmployeeId都有一個關聯的SupervisorId(見下文)。Linq to Sql - 查找祖先的分層查詢

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

如有必要,我可以緩存所有員工的列表以提高性能。

UPDATE:

我創建了以下粗略的方法來完成任務。它遍歷僱員。監督者關係一直到根節點。但是,這將爲每位員工發出一次數據庫調用。任何人都有更簡潔或更高效的方法?謝謝。

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

首先,歡迎您使用我的LINQ Extension Methods project中的分層查詢。我認爲可能有助於簡化代碼。

這裏的問題是,這將爲層次結構中的每個節點創建一個數據庫調用。就你的例子而言,你將有5次往返數據庫。

我會走一條不同的路徑,並創建一個存儲過程來爲我做這件事,並返回整套Employee對象。由於在返回對象(處理上下文)之前斷開對象,因此可以簡單地使用存儲過程的結果集創建新對象。

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來支持服務器端執行)。