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