0

NHibernateにインスパイアされた無限のDALリファクタリング煉獄の一部として、リポジトリパターンを使用して、UIレイヤーからNHibernateを腕の長さに保つようになりました。リポジトリからのLoadメソッドの例を次に示します。

public StoredWill Load(int id)
{
  StoredWill storedWill;
  using (ISession session = NHibernateSessionFactory.OpenSession())
  {
    storedWill = session.Load<StoredWill>(id);
  }
  return storedWill;
}

私のウェブサイトがISessionが何であるかを知らないという事実が大好きです。

当然、上記のメソッドはStoredWillをロードせず、プロキシを返すだけなので、遅延初期化の例外が発生し始めました。プロキシのプロパティにアクセスすると、ISessionのスコープ内にいる時間が長くなるため、例外が発生します。何が起こっているのか気づいたとき、私は大声で笑いました。

私はこれを次のように修正しました:

public StoredWill Load(int id)
{
  StoredWill storedWill;
  using (ISession session = NHibernateSessionFactory.OpenSession())
  {
    storedWill = session.Load<StoredWill>(id);
    string iReallyCouldntCareLess = storedWill.TestatorLastName;
  }
  return storedWill;
}

しかし、それはすべて少しばかげているようです。もう少しエレガントなパターンを使用している人はいますか?

皆大好き。

デビッド

4

4 に答える 4

4

依存性注入を使用し、コンストラクターを介して ISession をリポジトリ クラスに渡します。これが、複数のリポジトリが同じトランザクションに参加できるようにする唯一の方法です。

トランザクション境界が定義されている場所であるため、Web サイトには ISession に関する知識が必要です。ISession が HttpRequest モジュールまたは Global.asax でのみ参照されるように、要求ごとのセッション パターンを使用できます。または、フレームワークを使用するか、NHibernate を採用してページ上のトランザクションを制御することもできます。

于 2010-07-19T21:04:27.457 に答える
1

ncommon フレームワークを確認してください。この種のタスクに最適なフェッチ戦略の優れた実装があります。これがどのように実装されているかについては、著者のブログで詳しく読むことができます。

また、セッションの使用状況が少しずれていることにも注意してください...実際には、セッションのライフサイクルをより高いレベルで制御する必要があります(フロントエンドに応じて、コントローラーまたはhttpmoduleレベルなど)。リポジトリ アクションごとに新しいセッションを開くことは、nhibernate の世界では主要なアンチ パターンです。

于 2010-07-19T18:57:21.377 に答える
1
public StoredWill Load(int id)
{
  StoredWill storedWill;
  using (ISession session = NHibernateSessionFactory.OpenSession())
  {
    storedWill = session.Load<StoredWill>(id);
    // force an eager load within the session
    NHibernateUtil.Initialize(storedWill.TestatorLastName);
  }
  return storedWill;
}
于 2010-07-19T19:05:50.517 に答える
0

問題の一部は、Session.Get()の代わりにSession.Load( ) を使用していることです。

この 2 つの詳細な説明については、 Ayende Rahien の記事 - The difference between Get, Load and querying by idを参照してください。

Session.Load()を呼び出すと、指定した Id のプロキシ オブジェクトを作成するように nhibernate に指示されます。この nhibernate を実行すると、実際にはデータベースを呼び出してデータを取得することはありません。これは、データベースに存在しないものでSession.Load()を実行すると、例外がスローされることを意味します。オブジェクトにアクセスする前にセッションを閉じているため、プロキシ セッションが閉じられているため、データにアクセスできません。

簡単な修正は、コードを変更してSession.Get()を使用することです。これにより、StoredWill クラスがデータベースから読み込まれ、オブジェクトに必要なデータが入力されます。ただし、オブジェクト内に内部クラスまたはコレクションがある場合は、それらのプロキシを作成するだけであることに注意してください。一度にすべてを取得する必要がある場合は、多くのクエリ メカニズムの 1 つを使用して、必要な部分を熱心にロードするか、プロジェクションを使用できます。

これが理にかなっていることを願っています:)

于 2011-02-21T00:24:38.803 に答える