3

我有事件,它可以有很多事件類型。我試圖通過使用我定義的NHibernate映射來查詢數據庫。問題是,在定義子對象標準時,NHibernate會重複調用數據庫,而不是一次調用它所需的所有數據。這導致搜索速度極慢。NHibernate的多對多標準創建多個數據庫調用

的數據庫表如下:

Event 
-EventID 

EventType 
-EventTypeID 

EventEventTypeID 
-EventEventTypeID 
-EventID 
-EventTypeID 

Event類看起來是這樣的:

Id as Integer 
Types as IList(Of EventType) 

的事件類型類看起來是這樣的:

Id as Integer 
FullTitle as String 

沒有EventEventType類。

NHibernate的映射如下:

EventMapping資料

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") 

在開我的形式,下面的函數被調用,這臺FetchMode爲事件的類型屬性。

Public Function CreateListViewQuery(currentNHibernateSession As ISession) As NHibernate.ICriteria Implements IListViewQueryable.CreateListViewQuery 

     Return currentNHibernateSession.CreateCriteria(Of [Event])().SetFetchMode("Types", FetchMode.Join) 

End Function 

這是用來填充ListView,這非常迅速發生,只需一個電話到數據庫中的所有數據:

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,像這個(其中快速搜索我的用戶輸入):

.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多個電話,看起來像這樣(50,我選擇了TOP 50):

SELECT 
    types0_.* 
FROM 
    event.EventEventType types0_ 
     left outer join event.EventType eventtype1_ on types0_.EventTypeID=eventtype1_.EventTypeID 
WHERE [email protected] 

(其中@ P0爲每個被搜索返回的TOP 50事件)

我覺得只有第一個電話應該是必要的。

它是一個多對多關係的性質,這意味着NHibernate需要這些額外的調用?我的地圖中有什麼我錯過了?

也許重要的是,我使用了完全相同的技術來處理事件的字符串屬性,以及來自事件的一對多關係,並且只需要一次調用就可以進行搜索。這個問題似乎只存在於多對多的關係中。

對於長期問題的道歉,並感謝您獲得這個目標。我已閱讀了許多有關類似主題的問題,但找不到解決多次數據庫調用多對多關係的問題。

回答

3

您所描述的是nHibernate n+1問題(基本上執行的查詢數量與結果集大小成正比),根據查詢的複雜程度可能難以解決。

雖然不是一個顯而易見的解決方案是什麼爲我在過去的工作是要改變連接類型左外連接如下:

.CreateAlias("Types", "t", NHibernate.SqlCommand.JoinType.LeftOuterJoin) 
+0

哇 - 它的工作原理。現在只有一個調用數據庫。我很想知道這背後的邏輯。非常感謝您的幫助。 – phillyd