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
感謝。
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
感謝。
var managedEmployees = ctx.Employess.Where(x => x.ManagerId = 4).AsEnumerable()
如果你想立刻整個樹,解決方案更復雜。在SQL中,它最好用CTE完成,我不知道EF是否可以使用linq處理這個問題 - 更可能使用迭代解決方案。
你可以做類似
int id = 5;
do
{
employee= employeedata.FirstOrDefault(e => e.EmployeeId == id);
} while (employee != null && (id = employee.ManagerId) != 0);
,但它做,因爲它可能會卡在一個無限循環一個相當危險的事情。據我所知,除非您編寫存儲過程,否則無法直接進行遞歸查詢。
是的,我知道可以通過在存儲過程中寫入CTE來完成。我想看看是否有一種方法可以直接通過linq轉換爲sql表達式。似乎答案是朝着「不」的方向發展。 – stackoverflowuser 2010-11-01 19:26:49
嗯:)我沒聽到一個可以遞歸的表達式。我以爲你問如何使programmaticaly :) – 2010-11-01 19:36:18
這個.AsHierarchy()擴展方法可能有用:link。但是,這隻能通過提供一種簡單的方法將結果放入鏈接的對象中。爲了做到這一點,它只會獲取所有記錄並運行自己的本地遞歸查詢。
如果您正在查找LINQ查詢,該查詢將直接轉換爲通過LINQ to SQL進行遞歸SQL查詢,您將無法找到它。爲了獲得最佳性能,存儲過程中的CTE可能是您正在尋找的。如果你有一個非常簡單的頁面,無論如何都需要加載整個樹,AsHierarchy方法可能適合你的需求。
我不知道這是否是你想要什麼,但這裏是使用一些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 [] { };
}
}
4,3,1 ??你說什麼樣的算法? :)會發生什麼如果我選擇5? – 2010-11-01 19:02:59
@Serkan:這應該給出員工名單的ID:5,2 – stackoverflowuser 2010-11-01 19:05:16
我還是不能理解你。 2是managerId?如果是的,據我所知。你想要選擇EmployeeId和EmployeeId的managerId作爲EmployeeId? – 2010-11-01 19:08:54