LINQ to SQL层次结构问题

时间:2010-12-23 08:34:00

标签: c# sql-server linq linq-to-sql hierarchy

我从SQL Server中检索结果为

ProjectDetailID,ProjectID,ParentID,...,C1,C2,C3,...

其中C1表示(=>)companyOne,C2 => CompanyTwo ...等动态可以拥有'n'公司

暂时让我们只考虑3家公司,所以我得到了:

ProjectDetailID,ProjectID,ParentID,C1,C2,C3
10,1,0,NULL,NULL,NULL
10,2,1,NULL,NULL,NULL
10,3,2,90,NULL,NULL
10,4,2,NULL,60,NULL
10,10,1,70,NULL,NULL
10,5,10,20,40,NULL
10,13,2,NULL,NULL,NULL

我希望从以下结果使用LINQ(C#)

ProjectDetailID,ProjectID,ParentID,C1,C2,C3
10,1,0,180,100,NULL
10,2,1,90,60,NULL
10,3,2,90,NULL,NULL
10,4,2,NULL,60,NULL
10,10,1,90,40,NULL
10,5,10,20,40,NULL
10,13,2,NULL,NULL,NULL

问题在于,在父级别,我有一个公司的空值,但在它的孩子我有一些价值,我继续添加,并将其放在父公司只对应该公司。

我不是从哪里开始的。请分享您的想法。我希望使用C#

在LINQ中执行此操作

1 个答案:

答案 0 :(得分:3)

我认为我有解决方案。

我假设Project类有一个构造函数可以让我这样做:

var projects = new List<Project>(new []
{
    new Project(10, 1, 0, null, null, null),
    new Project(10, 2, 1, null, null, null), 
    new Project(10, 3, 2, 90, null, null), 
    new Project(10, 4, 2, null, 60, null), 
    new Project(10, 10, 1, 70, null, null), 
    new Project(10, 5, 10, 20, 40, null), 
    new Project(10, 13, 2, null, null, null), 
});

那么解决方案就像这样:

var traverse = projects.ToLookup(p => p.ParentID);

Func<Project, Func<Project, int?>, int?> rollup = null;

rollup = (p, f) =>
{
    var result = (f(p) ?? 0) + traverse[p.ProjectID].Sum(p2 => rollup(p2, f));
    return result == 0 ? (int?)null : result;
};

var query = 
    projects.Select(p =>
        new Project(
            p.ProjectDetailID,
            p.ProjectID,
            p.ParentID,
            rollup(p, p2 => p2.C1),
            rollup(p, p2 => p2.C2),
            rollup(p, p2 => p2.C3)));

此查询的技巧是rollup的递归定义。要使它工作,必须使用两个语句声明和定义匿名函数(即定义不能内联)。

结果与您问题中的第二组数据相匹配。希望这就是你所追求的。