2

SQL クエリは次のとおりです。

select B.* from A inner join B on A.b_id = B.id where A.x in (1,2,3)

A <-> B 関係は多対 1 です

A でフィルタリングする必要がありますが、関連する B を取得します。

アップデート:

このNH QueryOverを試しました

Session.QueryOver<A>.Where(a => a.x.IsIn(array)).JoinQueryOver(a => a.B).Select(a => a.B).List<B>()

最初のクエリは関連する B の ID をフェッチし、他のクエリは関連する B を ID ごとに 1 つずつフェッチします (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 の例を見たいと思っています。

4

1 に答える 1

3

これは(少なくとも私のテストアプリケーションでは)機能します:

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を追加するだけ)が期待どおりに機能しない理由を見つけようとします。乞うご期待!

于 2013-02-12T13:09:58.330 に答える