1

私は、マネージャとそのチームに質問するこのクエリがTeamコレクションの最初のエントリのみを返す理由を理解しようとしています。どうやら、それは私が質問の最後にFirstOrDefaultを持っていたからです。 FirstOrDefaultがクエリ全体に適用される印象を受けましたが、チームコレクションにも適用されているようです。なぜこれらの2つのFluent nHibernateクエリが異なる結果を生成するのですか?

オリジナルクエリ(ショーチームで唯一の第一メンバー):

session.Query<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team) 
       .Fetch(p => p.Manager) 
       .FirstOrDefault(); 

完全なチームを返す新しいクエリ:

session.Query<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team) 
       .Fetch(p => p.Manager) 
       .ToList().FirstOrDefault(); 

このクエリを策定するための正しい方法でしょうか?回避策が必要なのは、これを正しく実行していないことを意味します。

背景 - マッピング:

これは、マネージャがIEmployeeとチームがIEmployeeのIListをされているとの基本的な階層関係です。 FirstOrDefaultは、あなたが期待通りにデータベース上で動作します。このクエリで

References(x => x.Manager).Column("ManagerId"); 
HasMany(x => x.Team) 
       .AsList(index => index.Column("TeamIndex")) 
       .KeyColumn("ManagerId"); 
+0

あなたは、問題のクエリはおそらく唯一の最初の参加レコードが返されることを意味している「ONLY次の1行をフェッチ」SQLを生成するので、これが起こっているか生成されたSQLから伝えることができます。 FirstOrDefaultをFetchで正しく動作させる方法は私には分かりません。 – kasey

答えて

1

私は同じ問題で苦労されています。私にとっては、これはNH 3.1 - > 3.3からアップグレードするときに発生しました。問題は、Linqでは、NHibernate 3.3が、 "Top(1)"ステートメントを含むSQLクエリを生成し、クエリの "Fetch"パートを効果的に殺してしまうことです。 LinqからQueryOverに切り替えることで解決しました。私はこれがうまくいくと信じて:

session.QueryOver<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team) 
       .Fetch(p => p.Manager) 
       .SingleOrDefault(); 
+0

興味深いことに、これは本質的に私がいくつかの実験の後で気づいたことです(私の答えを見てください)。はい、私はnHibernate 3.3を使用しています。私は、元の構文が何らかの例外を投げて無効であると言っているのかどうか疑問です。 – kasey

3
session.Query<IEmployee>() 
      .Where(p => p.PersonalNumber == PersonalNumber) 
      .Fetch(p => p.Team) 
      .Fetch(p => p.Manager) 
      .FirstOrDefault(); 

session.Query<IEmployee>() 
      .Where(p => p.PersonalNumber == PersonalNumber) 
      .Fetch(p => p.Team) 
      .Fetch(p => p.Manager) 
      .ToList().FirstOrDefault(); 

このクエリでは、ToListはデータベース上で動作します。すべての背後には、ToListの結果が反映されます。したがって、FirstOrDefaultは、ToListの結果セットからFirstOrDefaultを取得します。同じ結果を得るには、クエリに注文を追加する必要があります。 selectをorderなしで実行すると、Sqlは結果セットの同じ順序を認可しません。 ToListの結果の順序は、最初のクエリの内部順序と異なります。

+0

申し訳ありませんが、私はかなり理解していません。結果セットの順序(どれが1つのIEmployee、PersonalNumberのみが一意であるか)は、Employee.Teamコレクションに含まれるアイテムの数にどのように影響しますか? – kasey

0

問題は、デカルト製品(Fetchを使用)を要求していますが、FirstOrDefaultも使用しています。生成されたSQLから、デカルト積の最初の行(SQLが生成されたもの:「FETCH NEXT 1 ROWS ONLY」のみ)を取得するため、その組み合わせは機能しません。

私はこれをやりたいのなら別のタイプのクエリを書く必要があります。そうしないとToListの回避策を使用します。このインスタンスではあまり問題にはならないのですが、 。

例ソリューション:

session.QueryOver<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team).Eager 
       .Fetch(p => p.Manager).Eager 
       .SingleOrDefault();