3

我有事件,它可以有很多事件类型。我正在尝试使用我定义的 NHibernate 映射来查询数据库。问题在于,在定义子对象的标准时,NHibernate 会重复调用数据库,而不是一次调用它需要的所有数据。这会导致搜索速度极慢。

数据库表如下:

Event
-EventID

EventType
-EventTypeID

EventEventTypeID
-EventEventTypeID
-EventID
-EventTypeID

事件类如下所示:

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

事件类型映射

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

这用于填充列表视图,这发生得非常快,只需一次调用数据库即可获取所有数据:

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 个类似这样的调用(50 个,因为我选择了 TOP 50):

SELECT
    types0_.*
FROM
    event.EventEventType types0_
        left outer join event.EventType eventtype1_ on types0_.EventTypeID=eventtype1_.EventTypeID
WHERE types0_.EventID=@p0

(其中@p0 是搜索返回的 TOP 50 事件中的每一个)

我觉得只有第一个电话应该是必要的。

是否是多对多关系的本质意味着 NHibernate 需要这些额外的调用?我的映射中是否有我错过的东西?

也许重要的是,我对 Event 的 String 属性使用了完全相同的技术,并且 Event 中的一对多关系,并且只需要一次调用即可进行搜索。这个问题似乎只存在于多对多关系中。

为这个冗长的问题道歉,并感谢您走到这一步。我已经阅读了许多关于类似主题的问题,但找不到任何解决重复数据库调用多对多关系的问题。

4

1 回答 1

3

您所描述的是一个nHibernate n+1问题(基本上执行的查询数量与结果集大小成正比),这可能很难解决,具体取决于您的查询的复杂程度。

虽然不是一个明显的解决方案,但过去对我有用的是将连接类型更改为左外连接,如下所示:

.CreateAlias("Types", "t", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
于 2013-06-27T17:44:30.973 回答