是否可以使用NH QueryOver在一个查询中获取连接的实体?

时间:2013-02-12 09:27:49

标签: sql nhibernate inner-join queryover

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 没有子查询的示例,因为我倾向于认为子查询的效率较低。

1 个答案:

答案 0 :(得分:2)

这有效(至少在我的测试应用中):

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)无法按预期工作的原因。请继续关注!