简体   繁体   English

linq to sql递归查询

[英]linq to sql recursive query

EmployeeId  Name  ManagerId
------------------------------
1           A     null
2           B     null
3           C     1
4           D     3
5           E     2

just using this table, how can a linq query (using linq to sql) be written to fetch the parent data recursively. 只是使用这个表,如何编写linq查询(使用linq to sql)来递归获取父数据。

For instance if the Employer Id selected is 4 it should give list of employees with Id: 4, 3, 1 例如,如果选择的雇主ID为4,则应该给出Id:4,3,1的雇员列表

Thanks. 谢谢。

This .AsHierarchy() extension method may be useful: link . 这个.AsHierarchy()扩展方法可能很有用: link However, this only works by providing an easy way to throw your results into linked objects. 但是,这只能通过提供一种将结果抛出到链接对象的简单方法来实现。 In order to do that, it'll just get all the records and run its own local recursive query. 为了做到这一点,它只会获取所有记录并运行自己的本地递归查询。

If you're looking for a LINQ query that will directly translate to a recursive SQL query via LINQ to SQL, you won't find it. 如果您正在寻找将通过LINQ to SQL直接转换为递归SQL查询的LINQ查询,您将无法找到它。 For the best performance, a CTE in a stored procedure is probably what you're looking for. 为了获得最佳性能,存储过程中的CTE可能就是您正在寻找的。 If you have a really simple page that needs to load the whole tree anyway, the AsHierarchy method would probably fit your needs. 如果你有一个非常简单的页面需要加载整个树,AsHierarchy方法可能会满足你的需求。

I'm not sure if this is exactly what you want, but here is one recursive method that uses some linq that makes sure not to enter an infinite loop: 我不确定这是否正是你想要的,但这里有一个使用一些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 [] { };
    }

If you have linqpad installed you can test this with the following script: 如果安装了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 [] { };
    }
}
var managedEmployees = ctx.Employess.Where(x => x.ManagerId = 4).AsEnumerable()

If you want the whole tree at once, the solution is more complex. 如果您想要同时使用整个树,那么解决方案就更复杂了。 In SQL its best done with an CTE, I don't know if EF can handle this using linq- more likely an iterative solution would be used. 在SQL中,最好用CTE完成,我不知道EF是否可以使用linq来处理这个问题 - 更有可能使用迭代解决方案。

You could do something like 你可以做点什么

    int id = 5;
    do
    {
        employee= employeedata.FirstOrDefault(e => e.EmployeeId == id);

    } while (employee != null && (id = employee.ManagerId) != 0);

but it's a rather dangerous thing to do since it can get stuck in an infinite loop. 但这是一件相当危险的事情,因为它可能陷入无限循环。 As far as I know there's no way to make a recursive query directly unless you write a stored procedure. 据我所知,除非你编写存储过程,否则无法直接进行递归查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM