繁体   English   中英

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

[英]linq query to get all child elements by passing parent id

我在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查询中实现此目的?

您可以通过以下方式编写递归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();
}

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

这将需要一些递归,这通常不是最佳选择,在此之上添加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
}

看到它在行动

暂无
暂无

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

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