棘手的LINQ和嵌套集合

棘手的LINQ和嵌套集合,linq,Linq,我试图找出一种更简单的方法,我可以把下面的代码压缩成尽可能少的行。理想情况下,我希望从中获得一个IDictionary> var report = db.Reports.Select(rid => rid.ID == reportId) as Report; Dictionary<string, List<string>> notes = new Dictionary<string, List<string>>(); foreach (

我试图找出一种更简单的方法,我可以把下面的代码压缩成尽可能少的行。理想情况下,我希望从中获得一个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); 
     }
   }
 }

这应等同于:

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);
db.Reports
.Where(rpt=>rpt.ID==reportId)
.Cast()
.SelectMany(rpt=>rpt.SubReports)
.SelectMany(subRpt=>subRpt.SubReportItems)
.ToDictionary(
sri=>sri.标题,
sri=>sri.SubReportItemNotes.SelectMany(note=>note.NoteDetails);
笔记:
  • 代码的第一行使用
    .Select(rid=>rid.Id==reportId)
    ,但我假设这应该是
    Where
    而不是
    Select
    ,否则您将得到
    null
    的集合,因为
    Select
    结果将是
    bool
    类型,而
    as报告将为每个结果输出
    null
  • 这仅在所有
    子报表项的
    标题
    都是唯一的情况下才有效。可以想象,一个
    报表
    可能有10个
    子报表
    ,并且在这些
    子报表
    中有两个或多个
    子报表项
    具有相同的
    标题
    。如果是这种情况,那么您可以需要重新考虑一下,否则当您尝试添加字典中已经存在的
    标题时,将出现
    DuplicateKeyException
  • 说明: 基本上,我们采用了一组报告,并应用了一个条件,即我们只需要ID为所需ID的报告。就我个人而言,我会将其放在单独的一行中,并使用
    SingleOrDefault
    而不是
    where
    ,因为我只需要一个结果

    接下来,我们调用
    .Cast
    ,因为您正在使用
    作为报告
    ,所以我猜您需要它。这在实践中可能是多余的,也不必要的

    第一个
    。SelectMany
    调用将获得所有
    报告
    中的所有
    子报告
    。同样,此时我们可能只有一个
    报告
    对象

    现在我们有一堆
    子报表
    ,但我们确实希望获得所有
    子报表项
    ,因此我们使用另一个
    选择多个
    来获得这些


    现在,我们已经从所有(1)中的所有
    子报告中获得了所有
    子报告项
    Report
    s,我们创建字典。对于每个
    SubReportItem
    我们从
    Title
    属性创建一个键,然后对于值,我们使用最后一个
    SelectMany
    来获取与所有当前
    SubReportItemNote
    s关联的所有
    NoteDetails
    对象。

    谢谢!这帮了大忙。I对您的第一个注释确实有疑问。在我的代码中,我经常使用db.database.select(pid=>pid.Identifier==suppliedId);我得到了我的对象。我应该去哪里呢?@Pendragon87我不知道您使用的是什么数据访问技术,但是LINQ扩展方法
    Select
    将项目转换或项目项目投射到另一种类型。如果确实使用
    Select
    并获得您描述的结果,则不是通过LINQ提供程序。
    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);