问题
I am experiencing something weird when using NHibernate. I have opened up a codebase that I didn't write, and the one who did isn't here anymore. So I guess what I am looking for is more tips on debugging than anything else.
I am using NHIbernate 3.4 Linq provider, to query an entity, that has a many-to-one relationship to another entity.
What I see is the even though I never access the property that represents the many-to-one relation it is always hydrated. From looking at the queries through the NHibernate profiler, I can see that the property seems to be lazy loaded. Setting breakpoints with my debugger I can see that the property is never accessed.
When using the NHibernate profiler, I can see that it happens when I load the parent entity list, but not in the same query.
I have no idea why this happens, but it results in a N+1 problem.
The entities are defined in hbm.xml files.
So what I am asking for is input to where I should start digging. I feel that I have tried everything that I can think of already.
回答1:
I would almost for sure say, the issue is NOT on NHibernate, it is on the usage side (we both would agree I'd say)
So, what should we have (implicit or explicit) as the starting point is the lazy setting:
// class level
// by default lazy is turned on
<class name="Entity" ... lazy="true" ... >
...
// reference many-to-one level, also by default lazy
<many-to-one name="Entity" lazy="proxy" ... />
To avoid N+1 we should be sure that we use batch fetching with a batch-size
setting, see more here
// class/entity level
// ATTENTION - this is not implicit, we have to define that
<class name="Entity" ... lazy="true" ... batch-size="25" >
...
// collection level
// ATTENTION - this is not implicit, we have to define that
<bag name="Entities" ... batch-size="25">
...
Having that in place, now NHibernate itself will never load more than needed. So what could be the typical use case, when it is needed to load the Reference?
When overriding:
public override bool Equals(object obj)
{
}
public override int GetHashCode()
{
}
These methods should be (somtimes - for composite-id, even must be) overrided, to provide business unique key. Check, that any of the referenced value is not used for such comparison (e.g. combination of Country and Office is unique for some OtherEntity)
Last but not least, there could be issue with your debugger. Debugger is in fact effecting loading, because whenever we observe anything in the debug window ... we force NHibernate to load the lazy stuff.
That is suprisingly the most often source of "forced" loading. So, clear your observers...
Finally suggestion - create unit test to load just the root entity. Clear session at the end. Observe (with profiler) if there was some DB hit. You can more easily then check what was the cause...
来源:https://stackoverflow.com/questions/29085151/nhibernate-always-hydrates-many-to-one