I have a strange behaviour which I can't find any solution for days..
The behaviour I experience is the classic LazyInitializationException with no session or session was closed
which is usual when there's no contextual session and trying to access lazy loaded properties/collections, but this in not my case because I have:
Session-per-request session bounded with Spring.NET OpenSessionInViewModule
A session opened and bounded to the context (web request)
Entities with collection as "list" (mapping list collection) with lazy="extra" or with "set" (mapping set collection) (The issue is caused mainly with lazy=extra..)
It seems that the Count statement for extra cound be done, but accessing the whole collection throws the exception
After investigating the usual issues:
no session opened
the object is not bounded to any session
a call to Session.Clear or Session.Evict was made (so any lazy for the evicted instance will work)
the Spring.NET WebSupportModule is not registered
I found no explicit reasons of why this happen..
A strange behaviour is if I profile in NHprof, I see the exception in a new session, in other words, the contextual session works correctly,
but when the exception is thrown, that exception is visualized in a secondary session.. but NO code open a session, and a single, contextual session
is opened..
Anyone knows what other reasons could cause a situation like that?
Thanks in advance
It's difficult to diagnose without seeing some code, but the problem sounds very similar to this. In the linked case OpenSessionInView was being used in addition to setting the session context in another location (similar to your first two bullet points) and WebSupportModule was not registered (as in your last point).
On the other hand, I know nothing about Spring.NET.
Related
I am having a problem with the NHibernate default fetching behavior:
Lazy Fetching
Lazy fetching lets you decide how much of the object graph is loaded in the first database hit and which
associations should be loaded only when they’re first accessed. Lazy fetching is a foundational concept in
object persistence and the first step to attaining acceptable performance.
definition from: Nhibernate In Action, 2008
The problem:
I have a Submit button for example and I click it many times. On the server-side, I retrieve objects through navigating the object graph, for example:
User us = new GetUserById(userId);
if (us.Address.Street != null)
where One User has one Address on the DB Schema.
The first click works correctly, but if I click it quicker it thows the exception:
"Could not initialize proxy - no Session." Nhibernate
Is there any work around for this behavior?
thanks,
Tito Morais
you can use eager loading. see the below link:
http://nhibernate.info/doc/howto/various/lazy-loading-eager-loading.html
What would I need to be doing wrong to get an aggregate to be returned from the session (loading by id) that is an empty instance of the aggregate and not the entire graph. When I hit the actual url that is requested in my browser I see the full json object, hence, why I am suspicious of my session management.
I have tried recreating the situation in unit tests but no manner of poor session management can recreate what I am seeing. I see some null instances returned but never this strange 'empty' instance - which has an id but none of the properties have been hydrated.
I am seeing this behaviour in unstable build 438.
I just checked the behaviour by executing a query and am seeing the same issue, so it is not just when calling Load()
If you are seeing symptoms similar to those that I presented in the original question - the most likely scenario is that you are loading the entity via a 'stale' session.
I discovered that due to some IoC container config flaws on my behalf (remember, singletons are bad kiddies) that I was attempting to load via a session that had been hanging around far too long. I can't determine whether it had been disposed or not (I suspect not) but it was definitely living well past its creation date.
I am not sure this exactly explains the behaviour I was seeing, but I present it here in the hope of helping others.
I need some insights and thoughts about a refactoring I'm about to do to our web-app.
We initially used the session-per-request pattern with NHibernate and ActiveRecord by using the On_BeginRequest / On_EndRequest in the HttpApplication to create and dispose the session. Later on, we realized that any DB-related exceptions got thrown outside of our monorail-context, meaning that our rescues didn't kick in. As another sideeffect, we didn't have the option to fully skip creation of NHibernate sessions in any action, which in some cases would be desirable.
So we rewrote it to create sessions in Initialize() / Contextualize() in our base controller, and disposed them in the Dispose() of our base controller. We also Rollback the session in our rescue controller to prevent any half written changes to the DB. So far, so good. The reason for doing it in the Dispose() is because we want it to live through the view-rendering, because of lazy-loading reasons aswell as viewcomponents that needs to get a session (we could switch to units-of-work for the viewcomponents, but they don't seem to have a Dispose()...)
However, I'm experiencing some deadlock issues where we have started transacations in the DB that isn't getting rollbacked nor committed and I can't get my head around it, mostly because of the mess we've made with this approach...
So I found this article: http://hackingon.net/post/NHibernate-Session-Per-Request-with-ASPNET-MVC.aspx
And I thought, "Filters, we can use that in MonoRail too!", because it can kick in on BeforeAction and AfterRendering.
My questions then are:
What happens if an Exception occurs in the filter?
Will AfterRendering fire even if an Exception occurs in the action or the rendering?
Would you recommend this approach, if not, what are your suggestion instead?
Any pointers are very much appreciated!
You need an application error handler to care of exception handling.
Attach a debugger and find out.
Probably not (even though it is my article). It doesn't work with RenderAction. Best to use an IoC container to control the lifetime of connections.
I came across a very strange problem which never happened to me before.
In the login code:
var sqlLogin = db.LoginRetrieve(loginID, archived).SingleOrDefault();
//(db is the linq data context)
--problem:
If two users login at the same time, this line of code will throw an exception which is "The required column 'UserLoginID' does not exist in the results."
But if a single user logs in or two users don't click the button at the same time, it will have no exception.
Is there anyone can share some lights on this? Thanks in advance.
Han
I suspect that your DataContext is shared between requests.
Don't do that.
You should create a separate DataContext for each request.
Otherwise, you'll get nasty threading issues like this one. (DataContext isn't thread-safe)
In general, you should be very careful when sharing objects between requests (eg, statics or Application / Session state).
Unless you know specifically otherwise, you should assume that the object is not thread-safe and cannot be shared.
We are using NHibernate to manage our persistence in a complex modular windows forms application - but one thought keeps bothering me. We currently open a session on launch and open all objects through that session. I am worried that all loaded objects get loaded into the NHibernate session cache, so that they cant be garbage collected, and ultimately we will end up with the whole database in memory.
This never happens with web applications because web page requests (and even better Ajax requests) represent the perfect short lived transaction so a session can be opened and closed to handle each request.
However if I load an tree of objects in my forms application and put then into a navigation pane on the screen they may stay their for the life of the application - and at any point the user may click on them, resulting in our code needing to navigate the object relationships to other objects (which only works within an NHibernate session).
What do StackOverflow readers do to keep the benefits of NHibernate without the issues I describe?
Ayende and company usually recommend using a session per "conversation". This usually makes the session lifetime last for very short operations, so it behaves more like a web app.
For your tree case, you can use Bruno's solution #2 just fine. The objects can be lazily mapped. Then, every time you need to access a child collection, you start a conversation and reconnect the parent via ISession.Lock. Then when the databinding is done, close that session. Not too much overhead to maintain, just a few lines of code in any form that needs to carry a conversation; you can extend Form and the controls you're using to do this automatically if you're feeling sassy.
The tricky part, then, is concurrent edits from different sessions. Let's not go there!
I open a session when I need one, and I'll close it when I know that I won't need it anymore.
More specifically, for instance, if I have a form which lets me edit Customer information for instance, I'll open a session when the form gets instantiated, and I'll close the Session when the form is closed.
When I have 2 instances of that form open, I also have 2 session open.
I can see a couple of alternatives:
Eager-load the object tree (which, from what I can gather from the documentation is the default)
Detach the objects, intercept the "click" event, and load the data from the database then, with a new session. This one forces you to take care of collections by yourself, instead of relying on nhibernate, which may fall outside of the scope of the question (which asks for the benefits of NHibernate, one of which is collection management)
You can take a look to my posts on how to use uNHAddins to work with session per conversation in a Windows Forms application (uNHAddins is a project with some additionsns to NHibernate led by Fabio Maulo, current NH Lead)
The first post is this
http://gustavoringel.blogspot.com/2009/02/unhaddins-persistence-conversation-part.html
From there you have links to uNHAddins trunk.