Reputation: 15817
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
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
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
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
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