linq查询通过传递父ID来获取所有子元素

时间:2014-01-23 13:11:49

标签: c# linq

我在sql

中有一个代理表结构,如下所示
AGENCY_ID   AGENCY_NAME PARENT_AGENCY_ID
7              yyyyy    2
8               xxxx    0
9               aaaa    1
6               bbbb    0
1               cccc    7
2              ddddd    0
3              eeeee    1
4              fffff    2
5               ggggg   9

我想要一个LINQ查询来获取结果集,当我通过代理机构ID时,我应该从代理机构获得所有子机构

例如,如果我将参数代理商ID传递为“7”,那么我应该从代理商ID 7中获取所有子代理,孙子代理商,曾孙代理机构等。对于代理商ID为“7”,结果设置如下所示

AGENCY_ID   AGENCY_NAME PARENT_AGENCY_ID
    7          yyyyy    2      
    9          aaaa     1    
    1          cccc     7       
    3          eeeee    1    
    5          ggggg    9

如何在linq查询中实现此目的?

2 个答案:

答案 0 :(得分:1)

您可以通过以下方式编写递归lambda表达式,并使用LINQ:

public class Agency
{
    public int Id {get; set;}
    public int ParentId {get; set;}
    public string Name {get; set;}
}

void Main()
{
    var list = new List<Agency> {
        new Agency { Id = 7, ParentId = 2},
        new Agency { Id = 8, ParentId = 0},
        new Agency { Id = 9, ParentId = 1},
        new Agency { Id = 6, ParentId = 0},
        new Agency { Id = 1, ParentId = 7},
        new Agency { Id = 2, ParentId = 0},
        new Agency { Id = 3, ParentId = 1},
        new Agency { Id = 4, ParentId = 2},
        new Agency { Id = 5, ParentId = 9}      
    };

    Func<Agency,int, bool> isParent = null;
    isParent = (a,i) =>  a != null && 
       (a.Id == i || isParent(list.FirstOrDefault(x => x.Id == a.ParentId),i)); 
    var descendantsOf7 = list.Where(x=>isParent(x,7)).ToList();
}

但是,编写一个执行相同操作的递归方法可能会更具可读性和简单性。

答案 1 :(得分:1)

这将需要一些递归,这通常不是最佳的,在其上添加一层LINQ可能会使它更慢。我的建议是直接在SQL中执行此操作并将其公开为SP,您可以从应用程序代码中调用它。

就您的SP的外观而言,可以使用CTE来实现这一点。

CREATE PROCEDURE GetAssociatedAgencies
(
    @AgencyID int
)
AS
BEGIN
    SET NOCOUNT ON;
    WITH cte AS
    ( 
        SELECT T1.* FROM Agencies as T1
        WHERE AGENCY_ID = @AgencyID
        UNION ALL
        SELECT T2.* FROM Agencies as T2
        INNER JOIN cte AS C on T2.PARENT_AGENCY_ID = C.AGENCY_ID
    )
    SELECT * FROM cte;
END

存储过程通常作为方法添加到您的上下文中,因此这将像调用

一样简单
using (var context = new MyDataContext())
{
    var results = context.GetAssociatedAgencies(7);
    // query results
}

in action

相关问题