Reducing application startup time
减少应用程序启动时间
配置NHibernate的过程是相当密集的且需要花费一定的时间. NHibernate需要加载,解析和编译我们的映射并反射到model. 本节介绍如何减少NHibernate应用程序的启动时间.
准备
完成本章开始部分的Configuring NHibernate with App.config示例.
步骤
1. 为项目添加System.Configuration.dll引用.
2. 添加一个名为ConfigurationBuilder的类.
3. 添加下述using语句:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Configuration; using System.IO; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using Configuration = NHibernate.Cfg.Configuration;
4. 在ConfigurationBuilder中, 添加一个私有的字符串常量SERIALIZED_CFG = "configuration.bin";
5. 添加一个名为Build的方法,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public Configuration Build() { Configuration cfg = LoadConfigurationFromFile(); if (cfg == null) { cfg = new Configuration().Configure(); SaveConfigurationToFile(cfg); } return cfg; }
6. 添加一个名为LoadConfigurationFromFile的方法,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; } }
7. 添加一个名为IsConfigurationFileValid的方法,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; }
8. 添加一个名为SaveConfigurationToFile 的方法,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private void SaveConfigurationToFile(Configuration cfg) { using (var file = File.Open(SERIALIZED_CFG, FileMode.Create)) { var bf = new BinaryFormatter(); bf.Serialize(file, cfg); } }
9. 在Program.cs中, 使用下述代码替换原来的NHibernate配置代码:
var nhConfig = new ConfigurationBuilder().Build();
原理
NHibernate的配置类是可串行化的. 完全验证她的映射和设置需要花费一定的精力和时间. 应用程序第一次运行时, 可以不能避免这样的情况, 但是如果将配置对象串行化到磁盘, 我们就可以在下次运行她的时候并行化她,这样就可以让我们从繁重的工作中解脱出来.
IsConfigurationFileValid方法确保我们串行化的Configuration是最新的.如果代码或者是App.config文件已经更新,我们需要重新编译configuration对象.
通过比较不同文件的LastWriteTime来确定已经串行化的configuration是否是过时的. 我们使用BinaryFormatter来串行和并行化configuration.
提示:实际的configuration存在的位置是多变的
示例中I,只检查了程序集包含的ConfigurationBuilder类和 App.config. 如果你的configuration和映射存储在其他地方,请调整代码.
扩展
这种技术特别适合开发和测试这样的程序组:频繁修改代码,但是不变更映射和配置. 这样我们可以略过额外的解析以达到提高运行速度的目的,并且可以测试我们所做的修改.
她同样适用于桌面NHibernate应用程序. 因为用户是在焦急的等待你的应用程序的启动.但是不适用于生产环境下的Web应用程序,因为程序启动一次后会一直运行.