PDA

View Full Version : Question about support for nHibernate's default-lazy="true"


pjaffe
12-26-2006, 04:32 PM
Am I correct that Spring's support for nHibernate requires disabling the lazy initialization of nHibernate persistent objects?

I first tried using nHibernate 1.2 Beta with Spring 1.1 Preview 3 and got a System.InvalidOperationException:"Unable to make a reference to a transient module from a non-transient module" when using the Spring.Web bidirectional databinding.

When I dug into the problem, I found that the Spring.Web databinding attempts to generate runtime IL in Spring.Util.DynamicReflection.BaseDynamicMember.Se tupTargetInstance(...) that invokes property accessors on a nHibernate generated proxy object. If I explicitly set default-lazy="false" in the nHibernate mapping, the web tier databinding works since the target object is now the compile time defined domain object rather than a runtime generated nHibernate proxy.

It really seems like it would be nice to take advantage of nHibernate's default behavior of lazy initialization, particularly since I have a complex domain model which would only be partially exercised in any particular web request, and loading all dependent domain objects would be an unnecessary performance and memory hit.

I have started looking at the Spring nHibernate module and the HibernateTemplate class to see if it handles things any differently, but haven't really gotten any test cases up yet since I'm a bit confused by the nightly build whose source code contains the Spring.Data.NHibernate.Generic namespace but seems to have an unresolvable reference to the rest of the Spring.Data.NHibernate namespace which maybe depends on the previous NHibernate module...

My bottom line question is: Does Spring.NET's Web databinding support NHibernate's lazy initialization, and if so, what I am doing wrong?

Also, let me know if I should have posted this in the Web forum. I thought this question was so specifically targeted to NHibernate, that this was the better place.

Thanks,
Pete

Mark Pollack
12-26-2006, 05:12 PM
Hi,

The open session in view module should be used if you want to use lazy collections in the web tier. However, I'm sorry to report that this module needs some more work if you want to reuse the first level cache in the session and you should still demarcate your transactions. There are some forum posts with details.

I will think of some fix for the download for NH 1.2 such that it includes all the necessary files and you can build from the .sln out of the box. I'm using logical links in the project file to reuse the same source code from the NH 1.0 project. I'd like to avoid having copies in CVS. (svn links would help to some extent.) If you want to compile NH 1.2 at the moment you should download NH 1.0 and place it it a parallel directory so that the logical links can be resolved.

Thanks for your patience and feedback.

Mark

pjaffe
12-27-2006, 03:46 PM
Thanks for the quick response. I now see the OpenSessionInViewModule HttpModule and I can see how that opens the session on BeginRequest and closes on EndRequest (with the transaction demarcation stipulations you mentioned). As a result, I do believe calls to lazy loaded collections would succeed after the call to HibernateTemplate has already completed. This would be critical in my project and I appreciate the pointer. I'll have to play around with this a bit.

However, I don't believe this would address the problem I am having with the bi-directional databinding in the Spring.Web tier. That problem seems rooted in the inability to establish a data binding to a nHibernate proxy object that is generated at runtime and as a result exists in a transient .NET module. Should I post that question to the Spring.Web forum?

Regarding your version control strategy, could you work on NH 1.2 as a CVS branch off NH 1.0? I imagine you've already thought about that approach, and maybe you are trying to have NH 1.2 track the head of NH 1.0 which would require frequent merging of the branches... Anyway, I just created the parallel folder hierarchy and things compile now.

Thanks.

Pete

Mark Pollack
12-27-2006, 04:09 PM
Hi Pete,

Yes, please post it on the Web forum, the more eyes the better. Glad that you can compile/debug the source code. Let me know how it goes with the OpenSessionInView module.

My current thinking is to copy the source code into the local directory via a build event (one which would not fail if the parallel directory is not there as in the case of the cruisecontrol generated downloads). The nant build script is already aware to look "up and over" for the source code (though I now realize that the cruise control checkout process needs to check out that directory as well.) Anyway, I'll sort out this build related muck. For the reasons you mentioned, and the fact that they aren't real branches, I don't want to make branches to solve this problem.

Cheers,
Mark

pjaffe
12-28-2006, 05:08 PM
This thread diverged into two discussions, and I believe both should be carried further on other threads. Below is a status update on the two issues:


I was having a problem with Spring.Web databinding when using NHibernate's lazy loading (which uses runtime generated proxies). This resulted in an "InvalidOperationException: Unable to make a reference to a transient module from a non-transient module"
Status: This is a result of Spring.Core's Spring.Util.DynamicReflection.DynamicReflectionMan ager choosing to use a RunAndSave dynamic assembly (non-transient) when compiled with Debug flags. Using the Spring.Core Release build resolves this issue and any other workarounds are apt to be discussed in the following forum thread http://forum.springframework.net/showthread.php?p=4400

Discussion of the OpenSessionInViewModule's support for a single session that spans an entire request, thereby enabling things like NHibernate's lazy loading. Without that, Spring.Web DataBindings result in "LazyInitializationException: Could not initialize proxy - the owning Session was closed" during the Spring.Web.UI.Page.OnPreRender.
Status: I've started looking at OpenSessionInViewModule and I am still seeing the limitation of it only working for transactionally demarcated methods, and I agree with other forum posts that it would be important to have non-transactional NHibernateTemplate invocations share the same session. I'm still digging through a few threads related to this topic and I assume any further discussion would be held on one of them.

http://forum.springframework.net/showthread.php?p=2945
http://forum.springframework.net/showthread.php?p=3000



Thanks again for great support on these forums. So far it is looking fairly promising that I will use Spring.NET and its support for NHibernate in my next web project.
Pete