EmployeeId Name ManagerId
------------------------------
1 A null
2 B null
3 C 1
4 D 3
5 E 2
只需使用此表,如何编写linq查询(使用linq to sql)以递归方式获取父数据。
例如,如果选择的雇主ID为4,则应该给出ID为4,3,1的员工列表
感谢。
答案 0 :(得分:7)
这个.AsHierarchy()扩展方法可能很有用:link。但是,这只能通过提供一种将结果抛出到链接对象的简单方法来实现。为了做到这一点,它只会获取所有记录并运行自己的本地递归查询。
如果您正在寻找将通过LINQ to SQL直接转换为递归SQL查询的LINQ查询,您将无法找到它。为了获得最佳性能,存储过程中的CTE可能就是您正在寻找的。如果你有一个非常简单的页面需要加载整个树,AsHierarchy方法可能会满足你的需求。
答案 1 :(得分:2)
我不确定这是否正是你想要的,但是这里有一个使用一些linq的递归方法,确保不要进入无限循环:
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 [] { };
}
如果您安装了linqpad,则可以使用以下脚本对其进行测试:
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 [] { };
}
}
答案 2 :(得分:0)
var managedEmployees = ctx.Employess.Where(x => x.ManagerId = 4).AsEnumerable()
如果您想同时使用整棵树,解决方案会更复杂。在SQL中,最好用CTE完成,我不知道EF是否可以使用linq来处理这个问题 - 更可能使用迭代解决方案。
答案 3 :(得分:0)
您可以执行类似
的操作 int id = 5;
do
{
employee= employeedata.FirstOrDefault(e => e.EmployeeId == id);
} while (employee != null && (id = employee.ManagerId) != 0);
但这是一件相当危险的事情,因为它可能陷入无限循环。据我所知,除非你编写存储过程,否则无法直接进行递归查询。