SQL 查询是:
select B.* from A inner join B on A.b_id = B.id where A.x in (1,2,3)
A <-> B 关系是多对一
我需要按 A 进行过滤,但获取相关的 B。
更新:
我尝试了这个 NH QueryOver
Session.QueryOver<A>.Where(a => a.x.IsIn(array)).JoinQueryOver(a => a.B).Select(a => a.B).List<B>()
但是会导致N+1的查询序列:第一个查询相关B的ID,其他查询通过ID逐一获取相关B(通过NHProf分析)。我希望它一次性获取 B 列表。
更新2:
现在我用子查询解决了这个问题
Session.QueryOver(() => b).WithSubquery.WhereExists(QueryOver.Of<A>().Where(a => a.x.IsIn(array)).And(a => a.b_id == b.id).Select(a => a.id)).List<B>()
但我仍然希望看到一个没有子查询的 QueryOver 示例,因为我倾向于认为子查询效率较低。
最佳答案
这有效(至少在我的测试应用程序中):
var list = session.QueryOver<A>()
.Where(a => a.X.IsIn(array))
.Fetch(x => x.B).Eager
.List<A>()
.Select(x => x.B);
请注意,.Select() 语句是普通的 LINQ 语句,而不是 NHibernate 的一部分。
生成的 SQL:
SELECT
this_.Id as Id0_1_,
this_.B as B0_1_,
this_.X as X0_1_,
b2_.Id as Id1_0_,
b2_.SomeValue as SomeValue1_0_
FROM A this_ left outer join B b2_ on this_.B=b2_.Id
WHERE this_.X in (?, ?, ?)
当然,如果 A 是一个非常大的类,这并不是最佳选择。
带有子查询的仅限 NHibernate 的解决方案:
var candidates = QueryOver.Of<A>()
.Where(a => a.X.IsIn(array))
.Select(x => x.B.Id);
var list = session.QueryOver<B>()
.WithSubquery.WhereProperty(x => x.Id).In(candidates).List();
我将尝试找出最明显的解决方案(仅添加 Fetch().Eager)无法按预期工作的原因。请继续关注!
关于sql - 是否可以使用 NH QueryOver 在一个查询中获取连接实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14829282/