PDA

View Full Version : NHibernate.LazyInitializationException



nokiola
08-08-2006, 01:24 PM
Hi,

I have the following code:

IAccountServices accountServices = ctx["AccountServices"] as IAccountServices;

Account account = accountServices.GetAccount(10);
account.Name = "Modified name";
accountServices.UpdateAccount(account);

When I call UpdateAccount method I receive the following exception and I cannot persist modifications.

ERROR NHibernate.LazyInitializationException (null) - Could not initialize proxy - the owning Session was closed.


How can I keep the session open so that after everything goes ok?
I am using the above code snippet in a test case.

I assume ASP.NET applications behave differently and should need alternative way of configuring NHibernate session factory... I am thinking at OpenSession InViewModule.


Regards,
Robert

.ben
08-08-2006, 01:59 PM
Either the object needs to be associated again to a new session or tell the session that it needs to update the object by calling session.update.

Aleksei Kachanov
08-08-2006, 02:17 PM
Use OpenSessionInView Module

nokiola
08-08-2006, 02:21 PM
Probably OpenSessionInView module is OK for web apps.

How can I keep Spring managed sessions open in a WinForms application?

Regards,
Robert

Mark Pollack
08-08-2006, 04:45 PM
Hi Robert,

I would need to see your implementation to give a more precise answer but the usage pattern is that you need to demarcate your transaction, either programmatically or declaratively, and then use HibernateTemplate for your data access operations. The session will then be opened upon entering the transacted method and closed when exiting. If you take a look in NHDAOTest.cs in the test integration area you will see an example that combines multipel "dao" operations inside the AccountManager implementation. Hope this helps...

Cheers,
Mark

jnapier
08-08-2006, 11:28 PM
After diving into the code and stepping through it, I am starting to realize that the spring integration hides the NHibernate Unit of Work. There is a 1 to 1 relationship between a session and a transaction. The OpenSessionInViewModule attempts to bypass that for an Asp.Net application.

There are many other scenarios where a session should be more long lived than a transaction, unit testing is one example. The current implementation eliminates the value of the NHibernate 1st level cache.

I think we need to create an extension that will allow us to better control the life of a session. Without this, many of the benefits of using a Unit of Work will be lost.

Regarding the OpenSessionInViewModule, I think a custom config section should be created so that the configuration of the module is more explicit than using the appsettings.

Mark Pollack
08-08-2006, 11:49 PM
Hi,

The web area is probably the most common where a conversational style is used and open session module is for that approach. Otherwise the 1-to-1 mapping seems to cover the overwhelming majority of cases. The hibernate docs don't elude to any other strategies. Neverthless, I'm certainly open to discussion and new approaches. The reason I feel this way is that given the huge lead time there has been in Java-land regarding hibernate usage I haven't really seen many other approaches in widespread use. I don't think that the 1-to-1 approach makes the 1st level cache useless...but I'd like to ponder that a bit more.

I agree with the config approach to OpenSessionInViewModule you suggest and thought the same when doing a quick cleanup to get it in CVS.

The common scenario of unit testing and tx boundaries I think will be handled quite nicely using NUnit extensions such that an annotation like [TransactionalTests] at the class leve or [TransactionTest] at the method level, providing the same functionality as in Spring.Java with AbstractTransactionalDataSourceSpringContextTests or similar (ug the lack of that DataSource interface....)

Cheers,
Mark

jnapier
08-09-2006, 03:11 AM
Hi Mark. I'm glad that you are open to discussion on this topic because I think it will be an area of confusion for devs already using NHibernate such as myself. Here is a link to an article that describes the relationship between a NHibernate Session and Transaction.

http://www.hibernate.org/42.html

Of particular interest is the discussion on "The scope of a unit of work" at http://www.hibernate.org/42.html#A4

Here is a link to a sample app that attempts to show some best practices for NHibernate. http://www.codeproject.com/aspnet/NHibernateBestPractices.asp
Of particular interest are the NHibernateSessionManager and the use of System.Runtime.Remoting.Messaging.CallContext to provide proper storage of the ISession for Web apps, Windows apps, Unit Tests, or whatever.

I don’t particularly like the fact that a transaction is started on begin request but the API is very simple. NHibernate doesn't start a real database transaction on BeginTransaction anyhow.

There are many posts on the Spring forum where users have tried to remedy the situation. This link provides a good example
http://forum.springframework.org/showthread.php?t=10344&highlight=unit+work

With the current implementation, proxies and lazy loading will only work if a transaction is programmatically or declaratively demarcated. So Lazy Loading will work if the OpenSessionInViewModule is used but they will not work for non asp.net apps such as a windows app unless you keep a long running transaction. Since the current implementation will require a transaction to get Lazy Loading benefits, operations such as HibernateTemplate.Load are completely useless without the client declaring a transaction.

It would be nice to have the capability to control the scope of a session without the need to for a transaction. I would like to hear what others think about this.

As for the unit testing, are you suggesting that the attributes would control the life of the session and the transaction implementation? That sounds nice but there are still scenarios where you may want to commit a transaction in one test and then verify that the data was actually commited to the database after the transaction was committed. In this scenario more fine grained control of the session and transaction is required. I guess that should be capable now with the TransactionTemplate right? Maybe I just dont understand the AbstractTransactionalDataSourceSpringContextsTests to know what it actually does though. I will have to look at that and comment later.

.ben
08-09-2006, 08:33 AM
It would be nice to have the capability to control the scope of a session without the need to for a transaction. I would like to hear what others think about this

I believe Castle has a sessionscope and a transaction scope. Scopes (http://www.castleproject.org/index.php/ActiveRecord:Scopes).

Yet it appears to me that one would have to place a sessionscope outside your DAO classes, which increases coupling between your layers if the sessionscope is only used by NHibernate. If however this sessionscope can also imply i.e. a plain connection to a database, it would be much better.

Mark Pollack
08-09-2006, 02:09 PM
Hi,

I understand your points. BTW, we are planning to re-tool the thread local storage support, it is long overdue. This forum post (http://forum.springframework.net/showthread.php?t=572) contains some info on where we are heading. I'll let others reply, and in the meantime I will also chat with the Spring.Java folks directly to understand their perspective in more detail.

Cheers,
Mark

jnapier
08-10-2006, 06:27 AM
yes .ben. SessionScope would have to be controlled outside of the DAO classes. This is what the OpenInSessionViewModule does. To get the benefits of lazy loading, 1st level cache, transparent persistance, etc..., session management outside of the DAO is a must.

I dont think it would work much different than the way it is set up right now. If there was an open session, the DAO would attach to that session and use that session for data operations. If there was no session the DAO would open the session do some work and then close it exactly how it does now.

.ben
08-10-2006, 08:24 AM
With the OpenInSessionViewModule, you still have a 'centralized' place to find your sessionmanagement. Your session code isn't located anywhere else.

I currently use my own SessionManager, which binds itself to the running System.Transaction. Each dao requests a session from the sessionmanager, if there is a System.Transaction they all get the same one. If there is no System.Transaction they all get a different session.

My goal is allways to decouple and use most of the standard .NET functionality. Having a session- and/or transaction scope outside the DAO is no problem per se, if it's still centralized and manageable(like the OpenSessionView). If you want to change your DA layer, you only need to change your specific dao classes and get rid of the OpenSessionView. You would not need to look for other DA code located anywhere else. That's also why I think support for the .net Transactionscope is important, it's standard .net so if I use hibernate dao's or just plain sqlcommands they can be rollbacked/committed the same way, there's also an msdn article demonstrating transactionality for plain .net objects, using System.Transaction.

Maybe I'm just pushing it, just my 2 cents.

Mark Pollack
08-10-2006, 03:15 PM
Hi,

Ben, the strategy you are using is a 1-to-1 mapping of session and transaction. That is currently what is done functionaly speaking in the exisiting spring nhiberate codebase. The difference is in the programmatic api, which for spring.net isn't the "standard" using (txscope) but that is something I would like to support. I'm always in favor of not having any active tx demaraction in the codebase but that doesn't mean we shouldn't support it. The issue at hand to me seems to be if there should be a seperate, equally programmatic way to control session scope - essentially what is in castle. I really appreciate the conversation guys....

Cheers,
Mark

.ben
08-10-2006, 03:50 PM
Certainly support for it would be great, but I'll keep saying it should be possible to use that mechanism for other stuff ;). If I'm using a plain sql DA layer, map a connection to a session perhaps and a Dbtransaction to a transaction... anyway you get the idea.

Mark Pollack
08-10-2006, 04:09 PM
Hi,
Yup, certainly. This is a feature, mix of ado.net and nhibernate, etc., within a single transaction boundary, that is in Spring.Java and I have it on my todo list. I gotta get a jira project started for nhibernate so this is all more transparent. The interesting part is that since in .net 2.0 ado.net itself is aware of the standard tx scope one wouldn't necessarily need to use adotemplate to get that behavior. The whole thread-local-storage of the current transaction approach is very nice to have baked into the raw apis, but hopefully people find value add to adotemplate anyway.

Cheera,
Mark

nokiola
08-10-2006, 04:17 PM
I'd like to give my 2 cents regarding the management of session and transaction scope in Spring.NET + NHibernate scenarios.

Currently I see a few usage scenarios for sessions and transactions and I believe that Spring.NET should allow to cope with each of these scenarios:

1. NON web application - multiple NHibernate sessions open simultaneously.

Usage: possible multiple NHibernate sessions simultaneously in separate threads. Possible use: multithreaded windows service applications, multithreaded winforms.

Implementation overview: the session manager should allow creation of a new session if application requests so. Otherwise, the session manager should provide the same valid session.
Threads must keep track of their session and take care about closing it (maybe automatically via an aspect).

Currently, I have implemented in my NHibernate session manager this feature by storing the sessions in a hybrid dictionary using Thread.CurrentThread.GetHashCode() as key. Each thread requests a new session for doing its job and sessions are stored until disposal inside this dictionary. If a thread wants to reuse its session, for example, to start a new transaction, it automatically receives the same session from session manager based on its unique hashcode.

2. NON web application singleton - single NHibernate session, possibly multiple transactions
Usage: single threaded unit testing, console or winforms applications
Implementation: one session stored by the session manager.

3. NON web application - each transaction opens a new session which is automatically closed at the end of transaction. Currently, using Transaction attributes and other various transaction declaration modes, Spring.NET uses this mode.

4. Web mode - Session per request (aka OpenSessionInView)
Usage: one session per each request, possibly multiple transactions in one request.

Usually implemented as HttpModule inside web applications, session is stored in HttpContext.Current.Items (not in CallContext - not safe - see various posts regarding this subject)


I really believe that if Spring.NET would support the first two modes, it will be perfect for winforms and service applications. Also, will allow better performance due to the fact that the session will be reused and allow lazy loading of objects. Developer will have access to the NHibernate terrific unit of work.

Please consider these modes and share you opinions about supporting these usages scenarios in Spring.NET.

Wishing you all the best,
Robert

Tommy_Shen
11-20-2006, 02:32 PM
Probably OpenSessionInView module is OK for web apps.

How can I keep Spring managed sessions open in a WinForms application?

Regards,
Robert

I got this problem as you, but how do i configurate the web application for using OpenSessionInViewModule?

I configurate it in web.config as a httpmodule, but the problem aslo appeared.