2010-11-01 331 views
15
EmployeeId Name ManagerId 
------------------------------ 
1   A  null 
2   B  null 
3   C  1 
4   D  3 
5   E  2 

只是使用這個表,如何編寫一個linq查詢(使用linq to sql)來遞歸獲取父數據。linq to sql遞歸查詢

例如,如果ID選擇的僱主是4,應該給員工的名單與ID:4,3,1

感謝。

+0

4,3,1 ??你說什麼樣的算法? :)會發生什麼如果我選擇5? – 2010-11-01 19:02:59

+0

@Serkan:這應該給出員工名單的ID:5,2 – stackoverflowuser 2010-11-01 19:05:16

+0

我還是不能理解你。 2是managerId?如果是的,據我所知。你想要選擇EmployeeId和EmployeeId的managerId作爲EmployeeId? – 2010-11-01 19:08:54

回答

0
var managedEmployees = ctx.Employess.Where(x => x.ManagerId = 4).AsEnumerable() 

如果你想立刻整個樹,解決方案更復雜。在SQL中,它最好用CTE完成,我不知道EF是否可以使用linq處理這個問題 - 更可能使用迭代解決方案。

0

你可以做類似

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

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

,但它做,因爲它可能會卡在一個無限循環一個相當危險的事情。據我所知,除非您編寫存儲過程,否則無法直接進行遞歸查詢。

+0

是的,我知道可以通過在存儲過程中寫入CTE來完成。我想看看是否有一種方法可以直接通過linq轉換爲sql表達式。似乎答案是朝着「不」的方向發展。 – stackoverflowuser 2010-11-01 19:26:49

+0

嗯:)我沒聽到一個可以遞歸的表達式。我以爲你問如何使programmaticaly :) – 2010-11-01 19:36:18

7

這個.AsHierarchy()擴展方法可能有用:link。但是,這隻能通過提供一種簡單的方法將結果放入鏈接的對象中。爲了做到這一點,它只會獲取所有記錄並運行自己的本地遞歸查詢。

如果您正在查找LINQ查詢,該查詢將直接轉換爲通過LINQ to SQL進行遞歸SQL查詢,您將無法找到它。爲了獲得最佳性能,存儲過程中的CTE可能是您正在尋找的。如果你有一個非常簡單的頁面,無論如何都需要加載整個樹,AsHierarchy方法可能適合你的需求。

2

我不知道這是否是你想要什麼,但這裏是使用一些LINQ,使千萬不要進入一個死循環遞歸方法:如果你已經安裝了你linqpad

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 [] { }; 
    } 

可以用以下腳本測試:

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 [] { }; 
    } 
}