我正在使用鉴别器来处理项目状态。我正在使用NHibernate Profiler并注意到我的应用程序在选择我的状态方面变得非常疯狂。我总共有8个状态,NHibernate一直在查询:
SELECT state0_.State_id as State1_10_0_,
state0_.Name as Name10_0_
FROM States state0_
WHERE state0_.State_id = **3** /* @p0 */
当我选择状态为例如等于1,2,3,4或5的所有项时,触发此SELECT + 1的是什么。这将为我的项发出一个查询以及为每个状态发出5个查询。由于我经常查询项目(有状态),我正在执行大量的查询。
现在,看一下分析器,我不确定这是一个很大的问题,因为我查询的第一个状态需要6ms才能查询,6ms需要实现。所有其他状态显示为0ms查询和0ms实现。 NHibernate Profiler仍然将其显示为臭名昭着的SELECT + 1问题。
根据我的聚合根映射,我有:
References(x => x.State)
.Not.Nullable()
.Not.LazyLoad();
对于我的状态鉴别器映射,我有:
Id(x => x.Id, "State_id").GeneratedBy.Assigned();
Map(x => x.Name).Not.Nullable();
DiscriminateSubClassesOnColumn("State_id");
是否有一些我不了解歧视者的事情?
以下是导致问题的查询:
var items =
session.QueryOver(() => itemAlias)
.SelectList(x => x
.Select(xx => xx.Id).WithAlias(() => sentTo.Id)
.Select(xx => xx.State).WithAlias(() => sentTo.State)
.Select(xx => xx.Status).WithAlias(() => sentTo.Status)
)
.JoinAlias(() => itemAlias.State, () => stateAlias)
.WhereRestrictionOn(() => stateAlias.Id).IsInG(filters)
.Where(() => itemAlias.Status == Status.InProgress)
.TransformUsing(Transformers.AliasToBean<SentToDto>())
.List<SentToDto>();
罪魁祸首是
.WhereRestrictionOn(() => stateAlias.Id).IsInG(filters)
要解决我的SELECT + 1问题,我只需要通过一个鉴别器对象列表来查询,而不是单个id。
.Where(() => itemAlias.State.IsIn(new []{State.FooState, State.BarState}))
答案 0 :(得分:1)
听起来你急于加载状态本身,所以你的第一个查询是这样的:
SELECT * FROM Items where StateID IN (1,2,3,4,5)
然后,每个州有五个查询:
SELECT Name FROM State WHERE StateID = 1
SELECT Name FROM State WHERE StateID = 2
....
这样做是为了急切加载状态的名称,所以为了避免它,你应该在第一个查询中指定从“items”到“states”的连接,这样你就可以在那里获得名称,否则设置State对象如果您不需要除结果中的标识符之外的其他信息,则延迟加载。