鉴于此对象结构,我如何带回WorkItem,它的报告,行和学生,但只返回其学生姓名为&#的行39;鲍勃' (我想省略包含' Alice' Claire')的行。
工作项
---- Report1(在WorkItem.Reports集合中保存)
-------- ReportRow1(在Report.ReportRows集合中保存)
------------Student.Name =' Alice'-------- ReportRow2(保存在Report.ReportRows集合中)
------------Student.Name =' Bob'-------- 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>();
更新 我也尝试过这个,认为它只会在我真正尝试使用它们时会带回结果(它确实如此)但是看着日志,它仍然为每个学生做一个选择(我希望&#39;在哪里&# 39;最后一个foreach循环中的子句会带回只是我感兴趣的那个。
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 子句,我认为它会带回我想要的东西
答案 0 :(得分:1)
从我在此处看到的内容,您只选择 WorkItem
。您正在进行限制返回的WorkItems
的联接,但您仍然仅选择 WorkItem
而不是告诉它选择特定的Reports
,{{ 1}}等等。基本上你的查询就是这样说:“只给ReportRows
WorkItems
的{1}}可以加入名为Bob的学生”。请注意缺少:“然后选择 Id
仅包含相应的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;
行调用之前,甚至不会查询ReportRows
。此时,它对您要过滤的内容一无所知。你有几个选择。首先,您可以在加载someSelection
之后过滤第二个查询中的项目,如下所示:
WorkItem
或者您可以更改查询以明确选择工作项和相关行:// Filter on the second query:
var someSelection = found.Reports.First().ReportRows
.Where(rr => rr.Student.Name == "Bob");
。
最后,nhibernate能够指定应将哪些相关实体预加载到您选择的实体中。我知道实体框架允许你在相关实体上添加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);
以及WorkItem
名称为“Bob”的相关行。