w0051977
w0051977

Reputation: 15817

Must I use Eager loading if the session is disposed of?

Please see the code below:

public Enquiry GetByID(Guid personID)
{
    using (IUnitOfWork<ISession> unitOfWork = UnitOfWorkFactory.Create())
    {
        IRepository repository = RepostioryFactory.Create(unitOfWork);
        var Person = repository.GetById(personID);
        return Person;
    }
}

It is contained in an application service layer. Person is passed back to the Controller and loaded into a view. The view then errors because it cannot load Person.Collection (a list).

I believe this is because the collection is loaded using lazy loading and the unit of work and NHibernate session is closed once the view is reached. Must I use eager loading in this situation or am I misunderstanding something?

Upvotes: 0

Views: 102

Answers (4)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57307

Must I use eager loading in this situation or am I misunderstanding something?

Well, you want to, don't you? You are in a use case where you know that you want Person.Collection to be available, so why wouldn't you load it right away.

The trick is not to use the same repository implementation that you use when you want the collection to be loaded lazily (or not at all).

Udi Dahan wrote about this a number of times

Greg Young would caution you that the use of a fetching strategy is an implementation detail, and not part of the contract

Upvotes: 0

guillaume31
guillaume31

Reputation: 14080

Introducing a View Model layer instead of passing the raw entity over to the Controller will solve your problem since mapping to the Person View Model (inside the using clause) will access Person.Collection and trigger the loading.

Alternatively, you could have a whole Read side that doesn't go through the domain, as @EbenRoux suggests.

Upvotes: 0

Eben Roux
Eben Roux

Reputation: 13256

IMHO lazy loading is evil!

The idea behind a repository is to return an aggregate. That aggregate should contain all the relevant data that constitute the aggregate. It is never loaded in bits. An aggregate should, therefore, always be eagerly fetched.

If you remove UoW/ORM from the equation lazy loading just isn't an option.

You should try not to query your domain. If you have a situation where a single aggregate contains all the data you need and that data has been exposed then that would be OK.

However, I would recommend you use a read model. A simple query layer. Give that a try and you may just be surprised :)

Upvotes: 4

ajawad987
ajawad987

Reputation: 4672

I realized the session is ending before the method finishes (its wrapped in a using block), which is before your view code runs. So yes, you do need to eager load the items in the collection property in your Enquiry type you get back from the NHibernate session.

A better way is to setup the unit of work pattern so it wraps around the entire request in the pipeline. For example, if you have a Global.asax file, it has two methods called Application_BeginRequest and Application_EndRequest.

The Application_BeginRequest method would create a new NHibernate session which can be retrieved by your controllers.

The Application_EndRequest method would simply flush your session, saving any data changes to the underlying database.

I refer you to the following StackOverflow question for incorporating NHibernate sessions with the Global.asax component: NHibernate Session in global.asax Application_BeginRequest

Upvotes: 1

Related Questions