The process of configuring NHibernate is fairly intensive and takes some time. NHibernate has to load, parse, and compile all our mappings and reflect the model. In this recipe, I'll show you how to reduce the startup time of your NHibernate application.
Complete the Configuring NHibernate with App.config recipe from the beginning of this chapter.
System.Configuration.dll
.ConfigurationBuilder
.using System; using System.Configuration; using System.IO; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using Configuration = NHibernate.Cfg.Configuration;
ConfigurationBuilder
, add a private string constant SERIALIZED_CFG = "configuration.bin";
Build
with the following code:public Configuration Build() { Configuration cfg = LoadConfigurationFromFile(); if (cfg == null) { cfg = new Configuration().Configure(); SaveConfigurationToFile(cfg); } return cfg; }
LoadConfigurationFromFile
with this code:private Configuration LoadConfigurationFromFile() { if (!IsConfigurationFileValid()) return null; try { using (var file = File.Open(SERIALIZED_CFG, FileMode.Open)) { var bf = new BinaryFormatter(); return bf.Deserialize(file) as Configuration; } } catch (Exception) { // Something went wrong // Just build a new one return null; } }
IsConfigurationFileValid
with the following code:private bool IsConfigurationFileValid() { // If we don't have a cached config, // force a new one to be built if (!File.Exists(SERIALIZED_CFG)) return false; var configInfo = new FileInfo(SERIALIZED_CFG); var asm = Assembly.GetExecutingAssembly(); if (asm.Location == null) return false; // If the assembly is newer, // the serialized config is stale var asmInfo = new FileInfo(asm.Location); if (asmInfo.LastWriteTime > configInfo.LastWriteTime) return false; // If the app.config is newer, // the serialized config is stale var appDomain = AppDomain.CurrentDomain; var appConfigPath = appDomain.SetupInformation.ConfigurationFile; var appConfigInfo = new FileInfo(appConfigPath); if (appConfigInfo.LastWriteTime > configInfo.LastWriteTime) return false; // It's still fresh return true; }
SaveConfigurationToFile
with this code:private void SaveConfigurationToFile(Configuration cfg) { using (var file = File.Open(SERIALIZED_CFG, FileMode.Create)) { var bf = new BinaryFormatter(); bf.Serialize(file, cfg); } }
Program.cs
, replace the NHibernate configuration code with the following code:var nhConfig = new ConfigurationBuilder().Build();
NHibernate's Configuration class is serializable. Thoroughly validating the mappings and settings takes some effort and time. The very first time our application runs, we can't escape this, but if we serialize our Configuration object to disk, we can deserialize it the next time we run it, saving us all of this busy work.
The IsConfigurationFileValid
method ensures that the Configuration we've serialized is still fresh. If the executable or the App.config
has been updated, we need to rebuild our configuration object from scratch.
We compare the last write time of the various files to decide if the serialized configuration is stale. We use a BinaryFormatter
to serialize and deserialize the configuration.
This technique is especially suited for development and test suites, where we frequently change code, but may not change our mappings or configuration. We can skip all of the extra parsing and get running quickly, and test our changes.
It also works well for desktop NHibernate applications. Because a user is waiting on your application to launch, every second counts. It's not as useful for web applications in production because these basically launch once and stay running.