1

We're having an issue where I work. When we try to access a lazy loaded property on an NHibernate entity from within an MVC3 view, a "No Session" LazyInitializationException will be thrown. This only started cropping up on us in the last week, but we've been unable to narrow down the problem. There doesn't look like there's a simple solution though.

Notes:

  • Example of stacktrace: http://textsnip.com/613608
  • We don't Dispose(or wrap the Session in a using) anywhere in our projects. We let ObjectFactory handle that.
  • This only happens on our TeamCity testing environment when running regression tests(SpecFlow with WatiN). None of us are able to reproduce the problem on our dev machines.
  • This also doesn't happen consistently. While the tests that fail are usually the same tests, they don't fail all the time. Other tests that access pages that would hit some of the same views don't fail.
  • On the tests that do fail, they seem to weigh more towards lazy loaded collection initializing than non-collection, but both do happen.
  • While I know that it'd be better to eager load the entities whenever it's possible, due to the interdependency of a lot of our table models, it's not all that feasible at the moment.

What are we missing here?

rossisdead
  • 2,064
  • 1
  • 18
  • 30

2 Answers2

1

Your entity loading pattern is called open session in view and it is considered an anti-pattern. More on cons of this pattern here and here.

The recommended approach would be using some view models with pre-fetched data. But if you can't do it, you could pre-fetch model data using linq to nhibernate expand extension. There is an open-source library ITDT.Sentia, which provides typed expand extension or you can search for "nhibernate expand" in google. For more low level thing you can have a look at nhibernate fetching strategies.

For instance using ITDT.Sentia library and having following models:

public class User : BaseEntity
{
    public virtual string Email { get; set; }
    public virtual Company Company { get; set; }
}

public class Company : BaseEntity
{
    public virtual string Name { get; set; }
}

And assuming lazy loading of Company entity after fetching user, you can do something like:

IList<User> users = userRepository
  .GetAll()
  .Where(u => /*some constraints*/)
 // here you are telling nhibernate to make a join and eger load what you need
  .Expand(u  => u.Company) 
  .ToList();

As for different behavior in dev-environment I can only guess that somehow it is using some other configuration files, maybe there are different debug/release web.configs?

Community
  • 1
  • 1
0lukasz0
  • 2,463
  • 1
  • 18
  • 35
0

Are you binding directly to your object model in your views? That sounds like your problem in that you view binds directly to a domain object. Since the domain object has lazy collections it is trying to then load the collection elements on demand, which need an Nhibernate session.

You should be building up your complete view model in your controller method.

my suggestion would be to create a view model for each view that you have. Then when you are querying NHibernate, project directly into the model or use Automapper to convert your object model into the view model. The nice thing about direct projection is that the query through nhibernate will be more efficient because it will only select the columns you need.

Also see this article. http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

it's a create set of best practices for view models.

Fran
  • 6,005
  • 1
  • 21
  • 34
  • We're well aware that trying to use our actual entities in the view is considered a no-no, but we aren't in the position to change that at the moment. Also, this issue has just started cropping up recently, when it's worked fine for months. We know we need the NHibernate session, that's why we have ObjectFactory create it on a per-request basis, so it should still be alive when the model is used in the view. – rossisdead Apr 18 '12 at 16:26