限制使用 LINQ 返回的深度嵌套子记录



给定此对象结构,如何恢复工作项,它是报告,行和学生,但只有学生名称为"Bob"的行(我想省略包含"Alice"和"Claire"的行)。

WorkItem
----Report1(保存在 WorkItem.Reports 集合中)
--------ReportRow1(保存在 Report.ReportRows 集合中)
------------Student.Name = '爱丽丝'

--------ReportRow2(保存在 Report.ReportRows 集合中)
------------Student.Name = '鲍勃'

--------ReportRow3 (保存在 Report.ReportRows 集合中)
------------Student.Name = '克莱尔'

(对不起格式)

我以为这样的事情会起作用,但它仍然带回所有 3 行

    WorkItem found = (from workItem in session.Query<WorkItem>()
                      from report in workItem.Reports
                      from row in report.ReportRows
                      where workItem.Id == 1 && row.Student.Name == "Bob"
                      select workItem)
                     .SingleOrDefault<WorkItem>();

更新我也尝试了这个,认为它只会在我实际尝试使用它们时返回结果(它确实如此),但查看日志,它仍然为每个学生做一个选择(我希望最终 foreach 循环中的"where"子句只会带回我感兴趣的那个。

    var query = from workItem in session.Query<WorkItem>()
                      where workItem.Id == 1 
                      select workItem;
    WorkItem found = query.SingleOrDefault<WorkItem>();
    foreach (var report in found.Reports)
    {
        foreach (var row in report.ReportRows.Where(x => x.Student.Name == "Bob"))
        {
            Console.WriteLine("--" + row.Student.Name);
        }
    }
 

这是我目前根据Ocelot20的帮助尝试的最佳方法:

    var result = (from workItem in session.Query<WorkItem>()
                      .FetchMany(x => x.Reports) 
                      .ThenFetchMany(y => y.ReportRows.Where(z => z.Student.Name == "Bob"))
                  where workItem.Id == 1
                  select workItem);

唯一不起作用的是学生姓名的 Where 子句。如果我删除它,我会得到一个结果(尽管行太多)。如果我能得到正确的where子句,我认为它会带回我想要的东西

从我在这里看到的,你只选择一个WorkItem.您正在执行限制返回WorkItems的连接,但您仍然只选择一个WorkItem,而不是告诉它选择特定的ReportsReportRows等。所以本质上你的查询是说:"只给我一个Id为 1 的WorkItems,可以与名为 Bob 的学生一起加入"。请注意缺少:"然后选择仅具有适当ReportRowsWorkItem

我的猜测是你正在做这样的事情:

WorkItem found = (from workItem in session.Query<WorkItem>()
                      from report in workItem.Reports
                      from row in report.ReportRows
                      where workItem.Id == 1 && row.Student.Name == "Bob"
                      select workItem).SingleOrDefault<WorkItem>();
// Doing something to select `ReportRows` without filtering them:
var someSelection = found.Reports.First().ReportRows;

根据延迟加载设置的方式,ReportRows甚至不会被查询,直到您在someSelection行上调用它。此时,它对要筛选的内容一无所知。您在这里有几个选择。首先,您可以在加载WorkItem后筛选第二个查询中的项目,如下所示:

// Filter on the second query:
var someSelection = found.Reports.First().ReportRows
                                         .Where(rr => rr.Student.Name == "Bob");

或者,您可以直接更改查询以显式选择工作项和相关行:select new { workItem, reportRows = // select specific rows with a where clause here. } .

最后,还有 nhibernate 功能来指定应将哪些相关实体预加载到所选实体中。我知道实体框架允许您在相关实体上添加Where子句,但我还没有使用 nhibernate 来了解您是否可以执行以下操作:

var customers = session.Query<Customer>()
                       .FetchMany(c => c.Orders.Where(o => o.Amount == 100);

如果这有效,这可以应用于您的查询,以告诉 nhibernate 加载具有相关行的WorkItem,其中Student名称为"Bob"。

相关内容

  • 没有找到相关文章

最新更新