NHibernate:遅延読み込みを正常に設定できません
-
20-08-2019 - |
質問
ParentテーブルとChildテーブルがあります。子には、親テーブルへの外部キーが含まれ、1対多の関係が作成されます。流NHなNHibernateで定義するマッピングの一部を次に示します。
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
WithTable("Parents");
Id(x => x.Id, "ParentID")
.WithUnsavedValue(0)
.GeneratedBy.Identity();
Map(x => x.Description, "Description");
HasMany<Child>(x => x.Childs)
.LazyLoad()
.WithKeyColumn("ParentID")
.IsInverse()
.AsSet();
}
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
WithTable("Childs");
Id(x => x.Id, "ChildID")
.WithUnsavedValue(0)
.GeneratedBy.Identity();
References(x => x.Parent, "ParentID")
.CanNotBeNull()
.LazyLoad();
}
}
ご覧のとおり、リレーションにLazyLoadを設定しました。また、私のモデルクラスでは、すべてのプロパティが仮想として設定されていることに注意してください。
簡単なクエリの説明:
ICriteria crit = Session.CreateCriteria(typeof(Child))
.Add(Expression.Eq("Id", 18));
IList<Child> list = crit.List<Child>();
そして生成されたSQL:
SELECT this_.ChildID as ChildID5_1_,
this_.ParentID as ParentID5_1_,
parent2_.ParentID as ParentID4_0_,
parent2_.Description as Descript2_4_0_
FROM Childs this_
inner join Parents parent2_
on this_.ParentID = parent2_.ParentID
WHERE this_.ChildID = 18 /* @p0 */
ご覧のとおり、Parentテーブルで結合を行い、フィールド(idとdescription)を選択します。しかし、遅延読み込みを要求したのになぜそれを行うのですか?
クエリを次のように変更した場合:
ICriteria crit2 = Session.CreateCriteria(typeof(Child))
.SetFetchMode("Parent", FetchMode.Lazy)
.Add(Expression.Eq("Id", 18));
2つのSQLクエリが生成されます:
SELECT this_.ChildID as ChildID5_0_,
this_.ParentID as ParentID5_0_
FROM Childs this_
WHERE this_.ChildID = 18 /* @p0 */
これは私にとって良いことです:結合なし、親テーブルはクエリされません。 しかし、私はこの2番目のものも取得します。
SELECT parent0_.ParentID as ParentID4_0_,
parent0_.Description as Descript2_4_0_
FROM Parents parent0_
WHERE parent0_.ParentID = 45 /* @p0 */
再び親テーブルをクエリします。
これらの2つのクエリは、次の行で生成されます。
IList<Child> list = crit.List<Child>();
ここで何が起こっているのか全く知らない。誰か助けてもらえますか?
解決
Fluent NHibernateのバージョンに依存します。ある時点までは、すべてのエンティティが遅延ロードされない がデフォルトでした。これは、エンティティでlazy="false"
を明示的に設定することと同等です。これはもはや当てはまりませんが、その時点以前に何かを実行している場合、この動作が表示されます。
多対一/参照の遅延ロード設定は、ターゲットからのエンティティレベルの遅延ロードによってオーバーライドされるため、この古いバージョンのFNHで実行している場合、エンティティ設定はReferences(...).LazyLoad()
call mootをレンダリングします。
FNHの最新バージョンを使用していることを確認する必要があります。ただし、そうでない場合は、Parent
エンティティで遅延読み込みを明示的に設定する必要があります。これは、LazyLoad
のClassMap<T>
メソッドで実行できます。