Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过传递父id获取所有子元素的linq查询_C#_Linq - Fatal编程技术网

C# 通过传递父id获取所有子元素的linq查询

C# 通过传递父id获取所有子元素的linq查询,c#,linq,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

我在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时,我应该获得从该代理派生的所有子代理

例如,如果我将参数agency id传递为“7”,那么我应该获得从agency id 7派生的所有子agency、孙子agency、曾孙agency等。对于agency 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();
}
公共类代理
{
公共int Id{get;set;}
public int ParentId{get;set;}
公共字符串名称{get;set;}
}
void Main()
{
变量列表=新列表{
新机构{Id=7,ParentId=2},
新机构{Id=8,ParentId=0},
新机构{Id=9,ParentId=1},
新代理{Id=6,ParentId=0},
新机构{Id=1,ParentId=7},
新代理{Id=2,ParentId=0},
新机构{Id=3,ParentId=1},
新机构{Id=4,ParentId=2},
新机构{Id=5,ParentId=9}
};
Func 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的外观而言,这可以通过使用

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

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

请看。

这将需要一些递归,这通常不是最优的,在其上添加一层LINQ可能会使其更慢。我的建议是直接在SQL中这样做,并将其公开为SP,您可以从应用程序代码中调用它。这些递归层次结构是常用的公共表表达式(CTE)示例。看这篇文章-它有一个类似的例子:如果不是在linq中,你能帮助我编写sql存储过程来实现这一点吗!
using (var context = new MyDataContext())
{
    var results = context.GetAssociatedAgencies(7);
    // query results
}