views:

80

answers:

3

I'm currently using an attribute based approach to nhibernate session management, which means that the session is open for the duration of the Action method, but is closed once control is passed to the View.

This seems like good practice to me, however I'm running in to problems with lazy loaded collections. (This is complicated by the fact that some collections seem to be lazy loading even though they have Not.LazyLoad() set in the fluent mapping).

As I see it, my options are:

  1. Change my ISession management strategy and Keep the session open in the View
  2. Make better use of ViewModels (I'm currently not using them everywhere).
  3. Eager load all of the collections that are causing problems (maybe paged) (fluent problem not withstanding)

1 seems a bit wrong to be - but may be the 'easiest' solution. 2 is probably the proper way to go, but in some cases ViewModels seem slightly redundant, and I'm loathed to introduce more classes just to deal with this issue. 3 seems to be a bit of a dirty fix.

What do you think?

+1  A: 

consider your current usage as making implicit database operations. The object is sent to the View but the object contains proxies which when touched will try to return the data, and that requires a database operation.

Now,

  1. extending the ISession life including the View, its not wrong, as long as you are not doing explicit database calls...
  2. i wouldn't know about that
  3. This is actually the proper way regardless of the session EOL: you should try to do as less queries as possible per request and nhibernate gives you that ability via lazyless loading, futures, multihql/criteria etc.

note: although you may have mapped a collection as not lazy loaded it matters also How you query and get your desired result set. eg if you are using HQL then use a fetch join

Jaguar
Thanks for your answer - the queries that are not eager loading are based on ICriteria, not HQL.
UpTheCreek
+3  A: 

The best way to handle this (in my opinion anyways) is to introduce a service layer in between your UI and your repositories; It should take care of loading everything needed by the view and pass off a flattened (and fully populated) dto to the view.

Often, I go one step further and map the dtos returned from the service layer to view models, which often need to contain data that is very view-specific, and not appropriate for inclusion into the dtos coming from your service layer. Remember, Automapper is your friend when it comes to situations like this.

Using an open-session-in-view pattern is still perfectly acceptable, just don't have your views invoking lazy loading on entity models - this is almost always a horrible idea.

DanP
Thanks DanP. I've tried experimenting with Automapper. It looks very promising, however, when I map a collection on my Entity to a the collection on a ViewModel, this still seems to trigger lazy loading (even though the view only has access to the view model). I can only assume that references to the proxy are being passed in this case. Do you have any advice on how to force Automapper to copy across the real objects from the collection (rather than proxies)?
UpTheCreek
@UpTheCreek: simple, use collections of DTOs as well. Make it a pratice NEVER to send anything mapped in NHibernate (eg. your actual domain classes) from the service layer. It sounds daunting, but automapper really does make this a snap...
DanP
Ah yes, that works a treat, thanks!
UpTheCreek
+1 Isn't the whole point of open-session-in-view so that you can lazy load from the view? That's why I never bothered with it.
dotjoe
@dotjoe: Partially, but there are other advantages... for example: how about using the first level cache across multiple service layer calls? Batching of inserts/updates/deletes? There are valid reasons to keep the session open for the entire page lifecycle.
DanP
Yes, but service layer calls are done in controller. Or, are you talking about using RenderAction so multiple action methods use the same session?
dotjoe
@dotjoe: RenderAction is certainly an applicable example...if you're not using open-session-in-view, and instead want to control the session lifecycle at the controller level, it can be tricky to abstract out NHibernate's usage. This is usually why you'd want session management to live in something like an HttpModule (since it's really an infrastructure concern anyways)...
DanP
that makes a lot of sense. thanks
dotjoe
A: 

I don't think there's anything wrong about the first approach, and it will be the easiest to implement.

Session per request is a well known session management pattern for NHibernate.

Diego Mijelshon