【问题标题】:Is it possible to use NH QueryOver to fetch joined entities in one query?是否可以使用 NH QueryOver 在一个查询中获取连接的实体?
【发布时间】:2013-02-12 09:27:48
【问题描述】:

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

【问题讨论】:

  • 是的,有可能,我认为你至少应该先试一试!
  • 尝试在 Where(a => a.x.IsIn(array)) 之后添加一个 Fetch(a=>a.B).Eager 以摆脱 N+1 的问题。
  • @AndreLoker 它没有帮助,同样的问题。
  • 子查询,应该是这样,如何根据任何过滤器形式获得B的过滤集...等等

标签: sql nhibernate inner-join queryover


【解决方案1】:

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

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)无法按预期工作的原因。敬请期待!

【讨论】:

  • 带有急切关联获取和 LINQ-ing 的选项在某些情况下是子查询的一个非常好的替代方案,谢谢!
猜你喜欢
  • 2014-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
  • 2018-04-28
  • 1970-01-01
相关资源
最近更新 更多