linq to sql递归查询

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的雇员列表

谢谢。

这个.AsHierarchy()扩展方法可能很有用: 链接 。 但是,这只能通过提供一种将结果抛出到链接对象的简单方法来实现。 为了做到这一点,它只会获取所有记录并运行自己的本地递归查询。

如果您正在寻找将通过LINQ to SQL直接转换为递归SQL查询的LINQ查询,您将无法找到它。 为了获得最佳性能,存储过程中的CTE可能就是您正在寻找的。 如果你有一个非常简单的页面需要加载整个树,AsHierarchy方法可能会满足你的需求。

我不确定这是否正是你想要的,但这里有一个递归方法,它使用一些linq,确保不进入无限循环:

  public static IEnumerable GetTreeForEmployeeNumber(this IEnumerable 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 GetTreeForEmployeeNumber(this IEnumerable 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 [] { }; } } 

你可以做点什么

  int id = 5; do { employee= employeedata.FirstOrDefault(e => e.EmployeeId == id); } while (employee != null && (id = employee.ManagerId) != 0); 

但这是一件相当危险的事情,因为它可能陷入无限循环。 据我所知,除非您编写存储过程,否则无法直接进行递归查询。

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

如果您想同时使用整个树,那么解决方案就更复杂了。 在SQL中,最好用CTE完成,我不知道EF是否可以使用linq来处理这个问题 – 更有可能使用迭代解决方案。