Scenario: I have built an ASP.NET MVC application that manages my cooking recipes. I am using FluentNHibernate to access data from the following tables:
Question: Is there any way to tell NHibernate to load all data from all tables listed above and store it in memory / in NHibernate's cache so that there do not have to be any additional database requests?
Motivation behind question: The variety of many-to-many relationships poses a problem and would greatly benefit from that optimization.
Note regarding data: The overall amount of data is extremely small. We are talking about less than 100 recipes at the moment.
Instead of preloading everything, I would suggest loading once and then holding it as it's accessed.
NHibernate maintains two different caches, and does a pretty good job of keeping them in sync with your underlying data store. By default, it uses what is called a "first level" cache on a per-session basis but I don't think that's what you want. You can read about the differences at the nhibernate faq page on caching
I suspect a second level cache is what you need (this is available throughout your app). You'll need to get a cache provider from NHContrib (download the version that matches your version of NHibernate). The SysCache2 provider will probably be the easiest to set up for your scenario, as long as your app will be the ONLY thing writing to the database. If other processes will be writing, you will need to ensure that all are using the same cache as an intermediary if you want it to stay in sync.
The second level cache is configured with a timeout that you can set to whatever you need. Don't think it can be infinite but you can set it to long periods if you want (probably not a terrible idea to go back to DB from time to time though). If you want to preload everything up front, you can simply access all your entities from your global.asax's Application_Start method, but this shouldn't be necessary.
You will need to configure your session factory to use the cache. Call the .Cache(...) method when fluently configuring your session factory, it should be relatively self-explanatory.
You will also need to set Cache.ReadWrite() in both your entity mappings AND your relationship mappings. You can do this by convention or by calling Cache.ReadWrite() in your fluent mappings.
Something like:
public class RecipeMap : ClassMap<Recipe> {
public RecipeMap () {
Cache.ReadWrite();
Id(x => x.Id);
HasManyToMany(x => x.Ingredients).Cache.ReadWrite();
}
}
On the Cache calls in your mappings you can specify ReadOnly or whatever else you may need. NonStrictReadWrite is an interesting one, it can boost performance significantly but at an increased risk of reading stale data from the cache.