views:

288

answers:

2

I really don't know what the correct question is to figure out a solution to this problem. So here are some facts to provide context around the problem:

  • Our application is a winforms application that uses NHibernate.
  • Our application is distributed (client calls a service to execute use cases on NHibernate objects).
  • The invoice is the core aggregate root in the application and it is a very very large aggregate root (maybe 30 select queries to fetch each invoice... Invoice has notes. Invoice has approval associations. Invoice has line items. Line Item has taxes..etc..)
  • The application has a complex UI that operates on different aspects of the aggregate in a workflow-ish manner.
  • The UI has several save points where the entire aggregate needs to be updated under a unit of work.

The problem is navigating through the UI is very slow because when a save point is hit, we have to open up a new session and Nhibernate cannot take advantage of 1st level cache until the entire aggregate is reloaded from the database.

I need a solution that does the equivalent of what a long running 1st level cache would give us. What options are out there to achieve this? Burrow?

We have an optimal database, we run our distributed application locally during development (no round trip penalty), ... everything is working as expected except for flushing our aggregate root during save points.

I did some testing where I kept 1 session alive for the life of the application and the application was fast and very well. The downside to this approach is you have to explicitly evict every other domain object that comes through that long running session.

Hopefully I described the problem in enough detail that I wont get replies saying I need to index my database or check my router to make sure my network isnt the bottleneck :) Thanks in advance.

+1  A: 

This won't really help you this late in the game since it's an architectural decision (then again we added this half way through our project so it might) but it's a good thing to know about neverthless.. with that said you seriously want to consider the Command Query Seperation CQS stuff being put out there. Here is a good intro to the idea Command Query Seperation as an Architectural Concept.

The basic idea is that the model you have is used for commands (ex: add an item to an order, place the order) where as the querying against that data (what someone sees on a screen) is considered a separate concept that goes through a different mechanism.

So in our system we have a WCF service layer against which you can execute a command or ask for the results of a query which comes back as a dto.

We have a BusinessTransaction as an entity but we also have a BusinessTransactionView which provides a collapsed (OLAP style) view of a BusinessTransaction that provides all the details our screen needs.

Our concept of a BusinessTransaction is extremely heavy due to some 'out there' requirements which makes it costly to load one of these for display purposes only. By having a completely different way of querying we've been able to vastly increase the speed of our UI.

ShaneC
We have looked at CQS but it would be a major archichetural overhaul for our app. Thanks for the input. +1
A: 

Do not close the session. Just Disconnect it. When you're ready to commit Reconnect it. In this case you'll be able to utilize 1st level session cache (and there will not be a need to reload whole graph on Attach).