0

ASP.NET ページの 1 つのトレースを読んでいて、ユーザーが必要になるたびにページ ユーザーがデータベースから読み込まれていることに気付きました。それぞれISessionがオブジェクトをキャッシュすることになっているので、私はこれについて本当に当惑しています。

論理的には、問題は次の 2 つのいずれかである必要があります。

  1. ISessionキャッシュが正しく機能していません
  2. ユーザーがリクエストされるたびに、別のISession

問題は2番だと思います)。私は Castle Windsor を使用してオブジェクトのライフサイクルを管理しているので、誰かが問題を見つけるのを手伝ってくれる場合に備えて、使用しているコードの一部を投稿しました。Castle Windsor が管理しているクラスは次のとおりです。

  1. MooseUserRepository- MooseUser インスタンス (つまり、この場合はページ ユーザー) を管理するためのリポジトリ クラス
  2. KctcUnitOfWork- ISession のラッパー

MooseUserRepositoryKctcUnitOfWork次のようなコンストラクタ依存関係があります。

public MooseUserRepository(IUnitOfWork unitOfWork)
    {

    }

構成ファイルは次のようになります。

<component id="KctcUnitOfWork" service="Kctc.BusinessLayer.Kctc.IUnitOfWork,Kctc.BusinessLayer" type="Kctc.NHibernate.Kctc.UnitOfWork,Kctc.NHibernate" lifestyle="PerWebRequest"/>
<component id="MooseUserRepository" service="Kctc.BusinessLayer.Kctc.Repositories.IMooseUserRepository,Kctc.BusinessLayer" type="Kctc.NHibernate.Kctc.Repositories.MooseUserRepository,Kctc.NHibernate" lifestyle="PerWebRequest"/>

PerWebRequestライフスタイルに注意してください。

Castle Windsor コンテナは、呼び出される一種のユーティリティ クラスの単なる静的プロパティであるMoose.Applicationため、常に存在します。

private static IWindsorContainer _windsorContainer;

    public static IWindsorContainer WindsorContainer
    {
      get
      {
        if (_windsorContainer == null)
        {
          _windsorContainer = new WindsorContainer(new XmlInterpreter(HttpContext.Current.Server.MapPath("~/CastleWindsorConfiguration.xml")));
        }
        return _windsorContainer;
      }
    }

ページ自体には、次のような IMooseUserRepository インスタンスがあります。

private IMooseUserRepository _mooseUserRepository;
private IMooseUserRepository MooseUserRepository
  {
    get
    {
      if (_mooseUserRepository == null)
      {
        _mooseUserRepository = Moose.Application.WindsorContainer.Resolve<IMooseUserRepository>();
      }
      return _mooseUserRepository;
    }
  }

ページのユーザーは、次のようなプロパティによってアクセスされます。

private MooseUser PageUser
  {
    get { return MooseUserRepository.Load(ApplicationSettings.UsernameFromWeb); }}

これらの後続の呼び出しPageUserにより、重複した SQL コマンドが発生しているようです。

txtSubject.Enabled = PageUser.CanHandleLegalWorks;
    ddlDue.Enabled = PageUser.CanHandleLegalWorks;

明らかに、ロードされたオブジェクトをプライベート変数に保存することでこの問題を回避できMooseUserますが、私の理解では、ISessionこれは私のために行うはずです。

何がうまくいかないのか、誰でも推測できますか?

4

4 に答える 4

2

あなたは次のように述べています。

論理的には、問題は次の 2 つのいずれかである必要があります。

  1. ISession のキャッシュが正しく機能していません
  2. ユーザーがリクエストされるたびに、
    異なる ISessionを使用して読み込まれます

Nhibernate の第 1 (セッション) レベル キャッシュと第 2 レベル キャッシュを混同していると思います。

セッションは安価に製造して廃棄できます。Web アプリでは、通常、要求ごとに 1 つのセッションを使用します。エンティティを初めて取得またはロードすると、セッションの存続期間に限定された第 1 レベルのキャッシュに配置されます。セッションが閉じられ、リクエストの最後に破棄されると、セッションレベルのキャッシュ内のオブジェクトにアクセスできなくなります。実際、各ユーザーは異なるセッションによってロードされています。これは完全に正常です。

2 番目のレベルのキャッシュは、セッション ファクトリの有効期間に限定されます。第 2 レベルのキャッシュが有効になっている場合、主キーによってエンティティをロードすると、エンティティは第 2 レベルのキャッシュに格納され、キャッシュから削除されるまでデータベースに再度アクセスすることなく、すべてのセッションからアクセスできます。エンティティごとにキャッシュを明示的に有効にする必要があります。これはあなたが探している動作です。

参考文献:

編集

NHContrib プロジェクトからキャッシュ プロバイダーを選択する必要があります。おそらく Asp.Net キャッシュを使用する SysCache2 が必要ですが、必要に応じて MemCached や Velocity などを使用することもできます。また、Nhibernate Profilerを試してみることをお勧めします。ボンネットの下を突いて、Nhibernate が何をしようとしているのかを知る上で、これは非常に貴重であることがわかりました。

于 2011-01-07T15:41:31.067 に答える
1

質問で気づいたように、リポジトリに PerWebRequest ライフスタイルを使用しているため、リクエストごとに ISession (リポジトリで使用) が再作成されます。この動作は正しいものだと思います.ISessionはすべてのリクエストで作成され、NHに対するすべての操作が処理される必要があります.

1 つの ISession をシングルトンとして使用する場合は、リポジトリのライフスタイルをシングルトンとして宣言する必要があります。

アプリにはある種の SessionProvider または SessionFactory が必要だと思います。おそらく、シングルトンセッションでそれを行うことができます。

HTH

于 2011-01-07T15:16:45.137 に答える
1

私は問題が何であるかを理解しましたが、それは非常に微妙なものです。

次のコードでユーザーを取得しています。

private MooseUser PageUser
  {
    get { return MooseUserRepository.Load(ApplicationSettings.UsernameFromWeb); }
}

ApplicationSettings.UsernameFromWebASP.NET に関する限り、現在のユーザーのユーザー名を取得します。ユーザーのユーザー名は、Users テーブルの自然キーですが、主キーではありません! 私の知る限り、一次キャッシュは主キーによって取得されたオブジェクトに対してのみ機能します。

編集: この問題は、読み込まれたユーザーを HttpContext.Current.Items に詰め込み、この記事に従って読み込む前に最初にチェックするプロパティを作成することで解決しました。

于 2011-01-07T15:23:52.167 に答える
1

マッピングでnatural-id (Fluent NH の NaturalId) を使用して、まさにこの状況で第 2 レベルのキャッシュの有効期限をバイパスできます。

于 2011-01-07T15:53:13.487 に答える