优化nhibernate会话工厂,webApp的启动时间确实很慢

时间:2012-05-26 13:26:58

标签: c# asp.net-mvc-3 nhibernate fluent-nhibernate

我已经实施了测试应用。它使用流畅的nhibernate映射到mssql db中的db对象。因为我想学习微调nhib。 mvc3应用程序,我正在使用这个应用程序。用于测试目的,它只有一个带有10个枚举属性和一个字符串属性的简单实体。 所以,它实际上是光波,但根据nhibernate profiler的启动时间是4.37秒。对于一个只有少量行检查/取消选中属性的实体,这实际上很慢。

代码如下。 的 Domain.SessionProvider.cs

public static ISessionFactory CreateSessionFactory()
{
   var config = Fluently.Configure()
          .Database(MsSqlConfiguration.MsSql2008
          .ConnectionString(c => c.FromConnectionStringWithKey("myConnection")))
          .Mappings(m => m.FluentMappings.Add<FeaturesMap>())
          .ExposeConfiguration(p => p.SetProperty("current_session_context_class", "web"))
          .BuildConfiguration();

          return config.BuildSessionFactory();            
}

Global.asax中

public class MvcApplication : System.Web.HttpApplication
{   
   //SessionPerWebRequest is ommited here as well as other content
   public static ISessionFactory SessionFactory =
               SessionProvider.CreateSessionFactory();

    protected void Application_Start()
    {
       SessionFactory.OpenSession();
    }
}

在myController中,我有以下内容:

public ActionResult Index()
{
   return View(GetData());
}

private IList<FeaturesViewModel> GetData()
{
     List<Features> data;
     using (ISession session = MvcApplication.SessionFactory.GetCurrentSession())
     {
          using (ITransaction tx = session.BeginTransaction())
          {
              data = session.Query<Features>().Take(5).ToList();
              tx.Commit();

              var viewModelData = FeaturesViewModel.FromDomainModel(data);
              return viewModelData;
           }
      }
}

2 个答案:

答案 0 :(得分:20)

您可以通过缓存配置来改善(Web应用程序和Windows应用程序的启动时间)。以下课程将完成这项工作:

using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web;
using NHibernate.Cfg;

namespace NH32AutoMap.Core
{
    public class ConfigurationFileCache
    {
        private readonly string _cacheFile;
        private readonly Assembly _definitionsAssembly;

        public ConfigurationFileCache(Assembly definitionsAssembly)
        {
            _definitionsAssembly = definitionsAssembly;
            _cacheFile = "nh.cfg";
            if (HttpContext.Current != null) //for the web apps
                _cacheFile = HttpContext.Current.Server.MapPath(
                                string.Format("~/App_Data/{0}", _cacheFile)
                                );
        }

        public void DeleteCacheFile()
        {
            if (File.Exists(_cacheFile))
                File.Delete(_cacheFile);
        }

        public bool IsConfigurationFileValid
        {
            get
            {
                if (!File.Exists(_cacheFile))
                    return false;
                var configInfo = new FileInfo(_cacheFile);
                var asmInfo = new FileInfo(_definitionsAssembly.Location);

                if (configInfo.Length < 5 * 1024)
                    return false;

                return configInfo.LastWriteTime >= asmInfo.LastWriteTime;
            }
        }

        public void SaveConfigurationToFile(Configuration configuration)
        {
            using (var file = File.Open(_cacheFile, FileMode.Create))
            {
                var bf = new BinaryFormatter();
                bf.Serialize(file, configuration);
            }
        }

        public Configuration LoadConfigurationFromFile()
        {
            if (!IsConfigurationFileValid)
                return null;

            using (var file = File.Open(_cacheFile, FileMode.Open, FileAccess.Read))
            {
                var bf = new BinaryFormatter();
                return bf.Deserialize(file) as Configuration;
            }
        }
    }
}

要使用它,

private Configuration readConfigFromCacheFileOrBuildIt()
{
    Configuration nhConfigurationCache;
    var nhCfgCache = new ConfigurationFileCache(MappingsAssembly);
    var cachedCfg = nhCfgCache.LoadConfigurationFromFile();
    if (cachedCfg == null)
    {
        nhConfigurationCache = buildConfiguration();
        nhCfgCache.SaveConfigurationToFile(nhConfigurationCache);
    }
    else
    {
        nhConfigurationCache = cachedCfg;
    }
    return nhConfigurationCache;
}

然后在调用BuildSessionFactory之前,我们可以从缓存中读取配置文件,或者如果映射已经更改,则构建它并再次缓存它:

public ISessionFactory SetUpSessionFactory()
{
    var config = readConfigFromCacheFileOrBuildIt();
    var sessionFactory = config.BuildSessionFactory();

在这里您可以找到完整的样本:(^)。 +如果要使其工作,请从主应用程序的程序集中分离域类和映射定义程序集(因为如果映射定义程序集比缓存文件的LastWriteTime更新,ConfigurationFileCache类将删除缓存文件。)

答案 1 :(得分:2)

IIRC正确地说,在HttpApplication(或其子类,如MvcApplication)的构造函数中创建对象并不是一个好主意。最好在Application_Start处理程序中创建会话工厂。

您应该删除NHibernate探查器(因为所有探查器都可能影响测量)。相反,调用CreateSessionFactory()并使用Stopwatch类将其包围以获得准确的测量结果。

您的数据库服务器响应缓慢吗?由于连接池,这可能只在第一次出现时才会引起注意。

NHibernate确实需要一些时间进行初始化,但是使用一个轻量级实体的4秒似乎确实太多了。这当然受到测试系统的一般性能的影响。