you can cache projections with NH. I see it as a trade off. code
doesn't get much simpler than this
var entity = session.Get<Entity>(id);
var dto = Mapper.Map<Entity, Dto>(entity);
return View(dto);
the trade off is the number of database hits. this may or may not be a
problem. you could alter the query to pull the required graph back
var entity = session
.CreateQuery("from Entity e join fetch ... where
e.id = :id")
.SetParameter("id", id)
.UniqueResult<Entity>();
var dto = Mapper.Map<Entity, Dto>(entity);
return View(dto);
retrieving the entity is slightly more complex, but we reduce the
number of database calls. we still have the mapping of domain to view
model. which can be solved with projections
var dto= session
.CreateQuery("select new Dto(...) from Entity e join fetch ...
where
e.id = :id")
.SetParameter("id", id)
.UniqueResult<dto>();
return View(dto);
this makes the core more complex that before but we remove the need
for AutoMapper. in each instance there are trade-offs between
simplicity of code vs. performance. I don't jump straight to option
3, because I find the development gains of AutoMapper out weight the
performance hit required.
I am also very cautious of 2nd level cache. I treat it as a last
resort to performance improvements. 1st I ensure I have the least
number of remote calls, then I solve O^N operations, then I apply 2nd
level cache.