views:

815

answers:

4

I think I am stuck in the paralysis of analysis. Please help!

I currently have a project that

Unit of Work implementation in my case supports one NHibernate session at a time. I thought at the time that this makes sense; it hides inner workings of NHibernate session from ViewModel.

Now, according to Oren Eini (Ayende): http://msdn.microsoft.com/en-us/magazine/ee819139.aspx

He convinces the audience that NHibernate sessions should be created / disposed when the view associated with the presenter / viewmodel is disposed. He presents issues why you don't want one session per windows app, nor do you want a session to be created / disposed per transaction. This unfortunately poses a problem because my UI can easily have 10+ view/viewmodels present in an app. He is presenting using a MVP strategy, but does his advice translate to MVVM?

Does this mean that I should scrap the unit of work and have viewmodel create NHibernate sessions directly? Should a WPF app only have one working session at a time? If that is true, when should I create / dispose a NHibernate session?

And I still haven't considered how NHibernate Stateless sessions fit into all this! My brain is going to explode. Please help!

Update:

I found Ayende's Unit of Work implementation in Rhino Tools. I discovered that there are significant differences between his implementation and the one I did. His definitely supported multiple sessions. After further research I think it is best that I do the following:

  • Scrap my implementation of Unit of Work
  • Resign to using NHibernate's ISession and IStatelessSession objects directly from viewmodel. While in my opinion it's not ideal, I've already spent too much time on Unit of Work and it's not shaping up to what it is. Gotta apply KISS and YAGNI at some point. I can at least take solace in the fact that Ayende's article and a few others point out that using those directly is OK.
  • If I really really don't want to expose ISession, I can always use Castle.ActiveRecord, but I think that's not necessary.
  • I can re-use the Session Factory code, so the Unit of Work implementation is not a total waste.
  • Refactored my repositories to allow injection of both StatelessSession and Session, and use stateless if it's available: otherwise use regular session.

After all that, then I can apply the strategy of opening one session / stateless session per viewmodel and when view is disposed, have viewmodel flush / dispose the session / stateless session.

Sounds like a plan?

+1  A: 

What is your actual concern with having 10+ sessions active? Sessions are light-weight objects that can be used for heavy-weight operations. If the session isn't currently doing anything, it's kind of insignificant.

HTH,
Kent

Kent Boogaart
My problem is that I started by writing repositories, then realize that a unit of work would add to the repositories because I don't want to expose NHibernate workings to the viewmodels (I wasn't 100% sold on Nibernate then), so I did that. Now it seems my unit of work implementation is no good because that particular implementation only supports one session at a time. Maybe the answer lies in needing to refactor Unit Of Work to support multiple sessions.Sometimes I wish I didn't bother with Unit of Work and used NHibernate sessions right away. It's starting to smell bad.
Echiban
I think at this time I need direction on how a proper unit of work implementation would look here. My current implementation is very close to the unit of work link above.
Echiban
+1  A: 

Using UnitOfWork is seriously limiting in a client app, as all lazy-loading breaks. You lose part of what NHibernate is good at. You're also setting yourself up for runtime exceptions, because there is nothing in the NHibernate model to remind you not to use these features. I'd say Ayendes advice is good.

Robert Jeppesen
Explain why a UnitOfWork (basically the nH's ISession) breaks lazy-loading?
taoufik
Unit of Work, the way I implemented it, only allows one active session at a time. According to the unit of work article I read it was good for both client and web, so I went ahead and did it. Now I am coming to the conclusion that my unit of work need major rewrite to support multiple sessions.
Echiban
@taoufik: A Unit of work is short-lived (and kills the session when all work is done). The entity you are retrieving is likely to outlive your UnitOfWork. Any lazy-loading proxies will keep a reference to the session that is now killed. If you try to use any lazy-loading properties outside of your UnitOfWork, runtime exceptions ensue.
Robert Jeppesen
@Robert: I don't use my entities outside the scope of a unit of work. My units of work are implementing a business transaction, typically one unit of work per use-case, and a use-case can take days to finish. To me, the unit of work helps implementing (business) transactions without database locking. By reducing your unit of work to just the single commits or a bunch of reads, you should question yourself why you do have a unit of work.
taoufik
A: 

Personally I try to keep sessions open for as little time as possible. The main reason being that we use pessimistic locking on our main aggregate root (we're using domain driven design) so we want to release the lock as quickly as possible. Don't forget that since you're using NHibernate client side you can close your session and when you open a new one you can reconnect your disconnected entities back.

Personally even in an app which had many windows/tabs open at once I'd still use only one session at a time. I would open a fresh one when I need to retrieve data for a view or when changes need to be persisted.

At one point in our current app we implemented multi session support in our Unit Of Work but ended up taking it out when we realized we didn't have any use for it and it just complicated things.

ShaneC
A: 

Hello Echiban, did you find a solution to your problem, i am having the same problem? Thanks in advance. Rash

Rash