1

マネージャーとそのチームを求めるこのクエリが Team コレクションの最初のエントリのみを返す理由を突き止めようとしています。どうやら、クエリの最後に FirstOrDefault があったためです。FirstOrDefault がクエリ全体に適用されるという印象を受けましたが、Team コレクションにも適用されているようです。

元のクエリ (チームの最初のメンバーのみを表示):

  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();

このクエリを作成する正しい方法は何ですか? 回避策が必要なのは、これを適切に行っていないことを意味します。

背景 - マッピング:

これは、Manager が IEmployee であり、Team が IEmployee の IList である基本的な階層関係です。

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

3 に答える 3

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

このクエリでは、データベースで FirstOrDefault が期待どおりに機能します。

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

このクエリでは、ToList がデータベースで機能します。すべてのビハインドは ToList の結果に作用します。したがって、FirstOrDefault は ToList の結果セットから FirstOrDefault を取得します。同じ結果を得るには、クエリに注文を追加する必要があります。順序なしで選択を行うと、SQL は結果セットの同じ順序を付与しません。ToList の結果の順序は、最初のクエリの内部順序とは異なります。

于 2012-05-02T08:30:06.663 に答える
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();
于 2012-05-03T13:09:04.290 に答える
0

問題は、(Fetch を使用して) デカルト積を求めているだけでなく、FirstOrDefault も使用していることです。生成された SQL から、デカルト積の最初の行しか得られないため、その組み合わせが機能しないことがわかります (生成された SQL: "FETCH NEXT 1 ROWS ONLY")。

これを行う場合は、別のタイプのクエリを作成する必要があります。または、ToList 回避策を使用するだけで、データベースからの結果が 1 つしか期待されていないため、この場合はそれほど害はありません。

解決例:

session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team).Eager
                .Fetch(p => p.Manager).Eager
                .SingleOrDefault();
于 2012-05-03T12:22:41.597 に答える