I’m starting a series of posts “Don’t” about patterns and design decisions I consider bad. Some of them are learned the hard way, through bad judgment and painful experience. While at certain circumstances some of the patterns described can be useful, they are mostly don’t work well in a general case.
Open session in view
“Open session in view” (OSV) is a web-oriented (anti)pattern that opens ORM session at the beginning of the request and close it when view rendering is done (session is maintained by a servlet filter (Java) or http module (ASP.NET)).
Why one might need a session open for a duration of whole request?
The answer is really simple: this is the first thing that comes into mind when the rendering fails with LazyLoadingException, or LazyInitializationException, or whatever the ORM throws. This usually happens when the view is rendered directly from persistent entities with uninitialized lazy associations/collections.
Example
Consider the following menu in a classic eshop scenario:
And the following code passes the entities to the view layer:
1: using (var session = ORM.GetSession()){
2: return session.GetAll<ProductCategory>();
3: }
Assuming that lazy initialization is enabled for the Products collection of Category’s entity, view will fail to render the second level of the menu, because the session the entity was associated with is already closed.
To address those issues one may easily jump into OSV, but this decision has some strong drawbacks and generally hides the flaw of the design.
Drawbacks
OSV (anti)pattern has several drawbacks that limit it’s use and heavily influence design and performance:
- Works only in a 2-tier environment, which is acceptable in some, but not all cases
- Entities model is influenced by views: some of the associations that are needed by views are meaningless from the entities point of view. Category may have no Product collection, but rather a Product refers a certain category
- Can result in a large number of database queries, because of intensive lazy loading usage
Generally ORM sessions aren’t designed to survive failures in applying changes, therefore exception handling can became quite tricky. Up to some extent this can be addressed by Get after Post pattern.
Also while in short term OSV can solve the problem, it hides the real problem in the design: rendering views from entities.
What to use instead?
Well, there is really no need to render the view from entity model. Entity model’s purpose is to encapsulate behavior; displaying state is a query which has no behavior and therefore entity model is of a very limited value here.
A better choice is accessing the database directly, after all queries is the strong side of SQL.
It’s also worth looking at CQRS as a pattern that generalize this separation.