c# asp.net-mvc-3 nhibernate fluent-nhibernate
^

c# - Optimización de la fábrica de sesiones nhibernate, el tiempo de inicio de la aplicación web es muy lento



asp.net-mvc-3 fluent-nhibernate (2)

Tengo aplicación de prueba de implementación. que utiliza el mapeo nhibernate con fluidez al objeto db dentro de mssql db. Desde que quiero aprender afinar nhib. Aplicaciones mvc3, estoy usando esta aplicación. para propósitos de prueba que tienen solo una entidad simple con 10 propiedades enumerables y una propiedad de cadena. Por lo tanto, es realmente una onda de luz, pero el tiempo de inicio de acuerdo con el analizador de nhibernate es de 4.37 seg. Lo que es realmente lento para representar una entidad con pocas líneas marcadas / no seleccionadas.

El código es el siguiente. 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(); } }

Dentro de myController tengo los siguientes:

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; } } }


IIRC correctamente, no es una buena idea crear objetos en el contructor de HttpApplication (o sus subclases, como MvcApplication). Es mejor crear la fábrica de sesiones en el controlador Application_Start.

Debe eliminar el perfilador NHibernate (ya que todos los perfiladores podrían afectar las mediciones). En su lugar, ponga la llamada a CreateSessionFactory () y rodéelo con el uso de la clase Cronómetro para obtener una medición precisa.

¿Su servidor de base de datos es lento para responder? Debido a la agrupación de conexiones, esto solo puede notarse la primera vez.

NHibernate tarda un tiempo en inicializarse, pero 4 segundos con una entidad de peso ligero parecen demasiado. Sin embargo, esto se ve afectado por el rendimiento general del sistema de prueba.


Puede mejorar el tiempo de inicio (tanto de la aplicación web como de Windows) almacenando en caché las Configuraciones. La siguiente clase hará este trabajo:

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; } } } }

Para usar eso,

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; }

Y luego, antes de llamar a BuildSessionFactory, podemos leer el archivo de configuración de la memoria caché o, si las asignaciones han cambiado, compilarlo y volver a almacenarlo en la memoria caché:

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

Aquí puedes encontrar una muestra completa: ( ^ ). + Si desea que funcione, los ensamblajes de definiciones de asignaciones y clases de dominio independientes del conjunto de la aplicación principal (porque la clase ConfigurationFileCache eliminará el archivo de caché si el ensamblaje de definiciones de asignaciones es más reciente que LastWriteTime del archivo de caché).