我有事件,可以有很多EventTypes。我正在尝试使用我定义的NHibernate映射来查询数据库。问题是,在定义子对象的标准时,NHibernate会重复调用数据库,而不是调用所需的所有数据。这导致搜索速度极慢。
数据库表如下:
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映射如下:
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")
在我的表单打开时,调用以下函数,它为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中使用了一对多关系,并且搜索只需要一次调用。问题似乎只存在于多对多关系中。
为长期问题道歉,并感谢你们走到这一步。我已经阅读了很多关于类似主题的问题,但是找不到任何针对多对多关系重复数据库调用的问题。
答案 0 :(得分:3)
您所描述的是nHibernate n+1
问题(基本上执行的查询数量与结果集大小成正比),根据查询的复杂程度,这可能很难解决。
虽然不是一个明显的解决方案,但过去对我有用的是将连接类型更改为左外连接,如下所示:
.CreateAlias("Types", "t", NHibernate.SqlCommand.JoinType.LeftOuterJoin)