2010-11-01 342 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 [] { }; 
    } 
}