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

限制使用LINQ返回的深度嵌套子记录,linq,nhibernate,linq-to-sql,Linq,Nhibernate,Linq To Sql,给定这个对象结构,我如何返回一个工作项,它是报告、行和学生,但只返回学生名为“Bob”的行(我想省略包含“Alice”和“Claire”的行) 工作项 ----Report1(保存在WorkItem.Reports集合中) --------ReportRow1(保存在Report.ReportRows集合中) ------------Student.Name='Alice' --------ReportRow2(保存在Report.ReportRows集合中) ------------Stude

给定这个对象结构,我如何返回一个工作项,它是报告、行和学生,但只返回学生名为“Bob”的行(我想省略包含“Alice”和“Claire”的行)

工作项
----Report1(保存在WorkItem.Reports集合中)
--------ReportRow1(保存在Report.ReportRows集合中)
------------Student.Name='Alice'

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

--------ReportRow3(保存在Report.ReportRows集合中)
------------学生姓名='Claire'

(很抱歉格式化)

我原以为这样做行得通,但它还是把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>();
WorkItem found=(来自session.Query()中的WorkItem)
从workItem.Reports中的报告
来自report.ReportRows中的行
其中workItem.Id==1&&row.Student.Name==“Bob”
选择工作项)
.SingleOrDefault();
更新 我也尝试过这种方法,认为只有当我实际尝试使用它们时(确实如此),它才会返回结果,但查看日志,它仍然会为每个学生进行选择(我希望最后一个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);
        }
    }
 
var query=来自会话中的工作项。query()
其中workItem.Id==1
选择工作项;
WorkItem found=query.SingleOrDefault();
foreach(find.Reports中的var报告)
{
foreach(report.ReportRows.Where(x=>x.Student.Name==“Bob”)中的var行)
{
Console.WriteLine(“--”+行.学生.名称);
}
}
基于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);
var result=(来自session.Query()中的workItem)
.FetchMany(x=>x.Reports)
.ThenFetchMany(y=>y.ReportRows.Where(z=>z.Student.Name==“Bob”))
其中workItem.Id==1
选择工作项);

唯一不起作用的是学生名的Where子句。如果我删除它,我会得到一个结果(尽管行太多)。如果我能正确地得到where子句,我想它将从我在这里看到的内容中带回我想要的内容,您只选择了一个
工作项
。您正在执行限制返回的
工作项
,但您仍然只选择了一个
工作项
,而没有告诉它选择特定的
报告
ReportRows
等。因此,基本上您的查询是这样的:“只给我
Id为1的
WorkItems
,它可以与名为Bob的学生连接起来。”注意缺少:“然后选择该
WorkItem
,只包含适当的
ReportRows

我猜你在做这样的事情:

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;
var customers = session.Query<Customer>()
                       .FetchMany(c => c.Orders.Where(o => o.Amount == 100);
或者您可以将查询更改为显式选择工作项和相关行:
selectnew{workItem,reportRows=//在此处选择带有where子句的特定行。}

最后,nhibernate可以指定哪些相关实体应预加载到所选实体中。我知道实体框架允许您在相关实体上添加
Where
子句,但我还没有使用nhibernate知道您是否可以这样做:

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;
var customers = session.Query<Customer>()
                       .FetchMany(c => c.Orders.Where(o => o.Amount == 100);
var customers=session.Query()
.FetchMany(c=>c.Orders.Where(o=>o.Amount==100);

如果这样做有效,可以将其应用到您的查询中,告诉nhibernate加载
工作项
,其中
学生
姓名为“Bob”。

感谢Ocelot20的详细回复。使用“var someSelection…”我返回了正确的行(万岁!)但是,在所有这些结束时,我希望使用“someSelection”中保存的行填充单个WorkItem实例。如果我创建一个匿名类型(new{WorkItem,reportRows=…]),我想我需要以某种方式将结果转换回填充的WorkItem。建议的方法是什么?(我是LINQ的新手,谢谢你的帮助)如果
Fetch
方法允许where子句,那么“正确”的方法就是使用它们。你可能想先研究它们。如果它们不允许,就没有真正清晰的“LINQ-y”"除了将它们合并在一起之外的方法。注意,将它们合并在一起并清除旧的<代码> RePraveS> <代码>,并将过滤后的属性设置在该属性上可能会对NHiBiNess产生影响,我不知道。例如,它们可以考虑添加到<代码>工作项< /代码>中的任何<代码> RePraveStudio<代码>。成为新的实体并尝试将它们持久化到db。希望有nhibernate经验的人可以加入。好的,谢谢-我实际上一直在使用获取方法。尝试获取一个目前不会引发异常的方法:)我想我可能遇到了他们的LINQ提供程序的限制,虽然现在还为时过早。非常感谢您的帮助。我会在我有工作的时候再次更新。在一些搜索之后,似乎“Fetch Where”我建议的语法不受支持。这里有一个问题似乎可以解决您所面临的确切问题:快速更新:最佳解决方案(我指的是我唯一可以使用的解决方案)到目前为止,Ocelot20建议在“someSelection”上使用“Where”,但我很确定这是在从数据库加载所有行之后进行筛选,这显然是低效的。我还没有一个“Fetch/Join”风格的解决方案(甚至使用过滤器).如果我有进一步的了解,我会更新的。V感谢Ocelot20,因为他的回答给了我很多可以继续的地方。当然,任何其他建议都非常欢迎!