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