棘手的LINQ和嵌套集合

时间:2013-06-23 03:35:01

标签: linq

我试图找出一种更简单的方法,我可以采用以下代码并将其压缩为尽可能少的行。理想情况下,我想获得一个IDictionary>出于这一点。

 var report = db.Reports.Select(rid => rid.ID == reportId) as Report;
 Dictionary<string, List<string>> notes = new Dictionary<string, List<string>>();
 foreach (var subreport in report.SubReports)
 {
   foreach (var subreportitem in subreport.SubReportItems)
   {
     notes[subreportitem.Title] = new List<string>();
     foreach (var note in subreportitem.SubReportItemNotes)
     {
        notes[subreportitem.Title].Add(note.NoteDetails); 
     }
   }
 }

理想情况下,我曾经想做过这样的事情:

from report in db.Reports
where report.ID == reportId
from subreports in report.SubReports
from subreportitems in subreports.SubReportItems
from notes in subreportitems.SubReportItemNotes
//Unsure how to select into the desired dictionary...

1 个答案:

答案 0 :(得分:3)

这应该是等价的:

db.Reports
    .Where(rpt => rpt.ID == reportId)
    .Cast<Report>()
    .SelectMany(rpt => rpt.SubReports)
    .SelectMany(subRpt => subRpt.SubReportItems)
    .ToDictionary(
        sri => sri.Title, 
        sri => sri.SubReportItemNotes.SelectMany(note => note.NoteDetails);

注意:

  1. 您的代码的第一行使用.Select(rid => rid.Id == reportId),但我认为这应该是Where而不是Select,否则您最终会得到null的集合因为Select结果的类型为bool,而as Report会为每个结果输出null
  2. 仅当您Title的所有SubReportItems都是唯一的时,此方法才有效。可以想象,一个Report可以有10个SubReports,而SubReportsSubReportItems中有两个或更多个Title具有相同的DuplicateKeyException。如果是这种情况,那么您可能需要重新考虑一下,否则当您尝试添加字典中已有的Title时,您将获得SingleOrDefault
  3. 说明:

    基本上,我们正在处理这组报告,并应用我们只想要报告所需ID的条件。就个人而言,我会将其放在一个单独的行中,并使用Where代替.Cast<Report>,因为我只期望一个结果。

    接下来,我们仅仅因为您使用as Report而致电.SelectMany,因此我猜您需要它。在实践中,这可能是多余的,也是不必要的。

    第一次SubReports来电将获得所有Reports的所有Report。同样,我们此时可能只会有一个SubReports对象。

    现在我们有一堆SubReportItems,但我们真的希望获得所有SelectMany,因此我们使用另一个SubReportItem来获取这些内容。

    现在我们已经拥有来自所有(1)SubReport的所有Report的所有SubReportItem s,我们创建了字典。对于每个Title,我们从SelectMany属性创建一个键,然后对于值,我们使用一个最终NoteDetails来获取与当前所有SubReportItemNote相关联的所有{{1}}个对象{1}}秒。