多くの EventTypes を持つことができるイベントがあります。定義した NHibernate マッピングを使用してデータベースにクエリを実行しようとしています。問題は、子オブジェクトの基準を定義するときに、NHibernate が必要なすべてのデータに対して 1 回の呼び出しを行うのではなく、データベースへの呼び出しを繰り返し行うことです。これにより、検索が非常に遅くなります。
データベース テーブルは次のとおりです。
Event
-EventID
EventType
-EventTypeID
EventEventTypeID
-EventEventTypeID
-EventID
-EventTypeID
Event クラスは次のようになります。
Id as Integer
Types as IList(Of EventType)
EventType クラスは次のようになります。
Id as Integer
FullTitle as String
EventEventType クラスはありません。
NHibernate のマッピングは次のとおりです。
イベントマッピング
Table("event.Event")
Id(Function(x) x.Id).Column("EventID").GeneratedBy().Identity()
HasManyToMany(Of EventType)(Function(x) .Types).Table("event.EventEventType").ParentKeyColumn("EventID").ChildKeyColumn("EventTypeID").Cascade.All()
EventTypeMapping
Table("event.EventType")
Id(Function(x) x.Id).Column("EventTypeID").GeneratedBy().Identity()
Map(Function(x) x.FullTitle).Column("EventTypeFullTitle")
フォームを開くと、次の関数が呼び出され、Event の Types プロパティの FetchMode が設定されます。
Public Function CreateListViewQuery(currentNHibernateSession As ISession) As NHibernate.ICriteria Implements IListViewQueryable.CreateListViewQuery
Return currentNHibernateSession.CreateCriteria(Of [Event])().SetFetchMode("Types", FetchMode.Join)
End Function
これは、すべてのデータに対してデータベースを 1 回呼び出すだけで、非常に迅速に行われるリストビューの作成に使用されます。
SELECT TOP (50)
this_.EventID as EventID
, t3_.EventTypeID as EventTyp1_15_0_
, t3_.EventTypeFullTitle as EventTyp2_15_0_
FROM event.Event this_
inner join event.EventEventType types5_ on this_.EventID=types5_.EventID
inner join event.EventType t3_ on types5_.EventTypeID=t3_.EventTypeID
ただし、次のように Criterion.Expression を追加すると (QuickSearch はユーザー入力):
.CreateAlias("Types", "t", NHibernate.SqlCommand.JoinType.InnerJoin)
.Add(NHibernate.Criterion.Expression.Like("t.FullTitle", QuickSearch))
次のような呼び出しが 1 回あります。
SELECT TOP 50
this_.EventID as EventID12_6_
, types8_.EventID as EventID
, t3_.EventTypeID as EventTyp2_
, t3_.EventTypeFullTitle as EventTyp2_15_0_
FROM
event.Event this_
inner join event.EventEventType types8_ on this_.EventID=types8_.EventID
inner join event.EventType t3_ on types8_.EventTypeID=t3_.EventTypeID
WHERE t3_.EventTypeFullTitle like @p1
そして、次のように見えるさらに 50 の呼び出し (TOP 50 を選択したので 50):
SELECT
types0_.*
FROM
event.EventEventType types0_
left outer join event.EventType eventtype1_ on types0_.EventTypeID=eventtype1_.EventTypeID
WHERE types0_.EventID=@p0
(ここで、@p0 は、検索によって返された上位 50 個のイベントのそれぞれです)
これには最初の呼び出しだけが必要だと思います。
NHibernate がこれらの追加の呼び出しを必要とするのは、多対多の関係の性質ですか? マッピングに見逃したものはありますか?
おそらく重要なのは、Event の String プロパティと Event からの 1 対多の関係に対してまったく同じ手法を使用しており、検索に必要な呼び出しは 1 つだけです。この問題は、多対多の関係でのみ存在するようです。
長い質問で申し訳ありません。ここまでお付き合いいただきありがとうございます。同様のトピックに関する多くの質問を読みましたが、多対多の関係でデータベース呼び出しが繰り返されるという問題に対処するものは見つかりませんでした。