bryan costanich
bryan costanich

Reputation: 1739

Caching Fluent NHibernate ISessionFactory

We're building a mobile application, and we're evaluating NHibernate + Fluent for use with it. The problem is, the first time we create the ISessionFactory, it takes a full 2 minutes. even though the table structure is very simple (3 tables).

each call after that is extremely fast.

what i'd like to do is either cache the ISessionFactory between application restarts, or somehow speed up the creation of it in the first place.

Any ideas on if it's possible to cache? from all my reading, there's not much speeding it up.

Upvotes: 3

Views: 1484

Answers (3)

Phill
Phill

Reputation: 18796

You can serialize and save the configuration and load that up the second time around to reduce the time it takes to create. Tho if you make changes you need to blow away the old config and serialize a new version, otherwise you will be loading up old configuration.

I can't remember the code to do this tho, will try dig up an example.

Edit: http://vimeo.com/16225792

In this video at about 24 minutes in Ayende discusses Configuration Serialization.

Upvotes: 4

Tahbaza
Tahbaza

Reputation: 9548

Defining your ISessionFactory as a static variable (Shared for VB) and instantiating it only once upon application startup is how web apps get around this. I realize this may pose a challenge for a mobile app with memory efficiency demands but depending on the mobile platform you're using the application lifetime may not be as short as one would fear...

    public class NHHelper {
        private static string _connectionString;
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory {
            get {
                if (_sessionFactory == null) {
                            _sessionFactory = Fluently.Configure()
                                .Database(MsSqlConfiguration.MsSql2008.ShowSql()
                                    .ConnectionString(p => p.Is(_connectionString)))
                                .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetAssembly(typeof(NHHelper))))
                                .BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }

// this is called once upon application startup...
        public static void WarmUpSessionFactory(string connectionString) {
            _connectionString = connectionString;
            var factory = SessionFactory;
        }
// this is what you call to get a session for normal usage
        public static ISession OpenSession() {
            return SessionFactory.OpenSession();
        }
    }

Upvotes: 2

James Kovacs
James Kovacs

Reputation: 11651

When building the Configuration and ISessionFactory, NHibernate is parsing configuration and mappings to build up its runtime data structures. (This is true of EF and LINQ-to-SQL too, though its hidden within the context.) There is not much that can be done to eliminate this cost, though 2 minutes seems awfully long. Timing this code:

        var stopwatch = new Stopwatch();
        stopwatch.Start();
        var cfg = new Configuration();
        cfg.Configure();
        var sessionFactory = cfg.BuildSessionFactory();
        stopwatch.Stop();
        Console.WriteLine("Startup time was " + stopwatch.ElapsedMilliseconds + "ms");

It's a demo project and only has a few classes and mappings, but it took ~850 ms without the debugger attached. With the debugger attached, it was around 2 seconds.

Have you tried profiling your app to see where it is spending the 2 minutes?

Upvotes: 0

Related Questions