18

テストアプリを実装しました。これは、mssql db 内の db オブジェクトへの流暢な nhibernate マッピングを使用します。ファインチューンnhibを学びたいので。mvc3 アプリケーション、私はこのアプリを使用しています。10 個の列挙型プロパティと 1 個の文字列プロパティを持つ単純なエンティティを 1 つだけ持つテスト目的。つまり、実際にはライトウェーブですが、nhibernate プロファイラーによると起動時間は 4.37 秒です。これは、数行のチェック/チェックされていないプロパティを使用して 1 つのエンティティをレンダリングするのが非常に遅いです。

コードは次のとおりです。 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;
           }
      }
}
4

2 に答える 2

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 クラスはキャッシュ ファイルを削除するため)。

于 2012-05-27T04:28:44.110 に答える
2

IIRC は正しく、HttpApplication (または MvcApplication などのそのサブクラス) のコンストラクターでオブジェクトを作成することはお勧めできません。Application_Start ハンドラでセッション ファクトリを作成することをお勧めします。

NHibernate プロファイラーを削除する必要があります (すべてのプロファイラーが測定に影響を与える可能性があるため)。代わりに、CreateSessionFactory() への呼び出しを配置し​​、Stopwatch クラスを使用してそれを囲み、正確な測定値を取得します。

データベース サーバーの応答が遅いですか。接続プーリングのため、これは最初の機会にしか気付かない場合があります。

NHibernate は初期化に時間がかかりますが、1 つの軽量エンティティで 4 秒は長すぎるように思えます。もちろん、これはテスト システムの一般的なパフォーマンスの影響を受けます。

于 2012-05-26T15:03:46.407 に答える