2

NHibernate、Fluent NHibernate、および Spring を理解しようとしています。

ドメイン駆動型の設計原則に従い、以下で構成される標準的な階層型 Web アプリケーションを作成しています。

  • プレゼンテーション層 (ASP.Net)
  • 以下を含むビジネス層:
    • アプリケーション層 (基本的には UI 層に表示される一連のメソッド)
    • リポジトリ インターフェイスとドメイン コンポーネント (アプリケーション層で使用)
  • 永続層 (基本的に、ビジネス層で定義されたリポジトリ インターフェイスの実装)

ビジネス層への単一のリクエストの有効期間にわたって複数のリポジトリで共有できるように、NHibernate ISession をインスタンス化する方法を決定する手助けをしたいと思います。具体的には、次のことを希望します。

  • ISession インスタンスと任意のトランザクションをリポジトリの実装を使用して制御できるようにします (おそらく、IOC フレームワークのいくつかの側面、インターセプターによるものでしょうか?)

  • テストに適した方法で ISession インスタンスをリポジトリで使用できるようにします (おそらく、インジェクションまたは共有の「コンテキスト」抽象化を介して)

  • 不要なトランザクションが作成されないようにします (つまり、読み取り専用操作のみが実行された場合)。

  • SQLLite を使用するテストを記述できるようにする

  • Fluent NHibernate の使用を許可してください

  • リポジトリの実装がホスト環境を認識しないままにできるようにします。ビジネス層がプレゼンテーション層とインプロセスで実行されるのか、WCF の下 (IIS 内) で個別にホストされるのかはまだわかりません。 )。

この問題を解決するための最初の試みは、レジストリ パターンを使用することでした。ISession インスタンスを ThreadStatic プロパティに格納します。ただし、その後の読書は、それが最善の解決策ではないことを示唆しています (ASP.Net はページのライフサイクル内でスレッドを切り替えることができるため)。

あらゆる考え、部品の解決策、パターン名、最新のサンプル (NHibernate 2) へのポインタは、非常にありがたいものです。

4

2 に答える 2

1

あなたが説明していることは、ほぼそのままSpring.NETフレームワークでサポートされています。FluentNHibernate の場合のみ、Spring.NET にカスタム SessionFactory を追加する必要があります (多くのコードではありません。ここを参照してください: Spring.NET で Fluent NHibernate を使用する)。

すべてのリポジトリは同じ ISession を使用できます。リポジトリに SessionFactory を注入するだけで、Spring.NET のトランザクション サービスを使用できます。

試してみてください。かなり詳細なドキュメントがあります。

于 2009-10-29T09:01:39.683 に答える
1

私は Spring.NET を使用したことがないので、それについてコメントすることはできません。しかし、残りは私自身の経験と非常に似ているように思えます (または、それほど顕著ではないかもしれません。これらを実装したのは私たちが最初ではありません ;)。私も 1 つの真のベスト プラクティスを見つけるのに苦労したので、できるだけ多くのことを読み、独自の解釈を思いつきました。

私の状況では、トランザクション/セッション管理をリポジトリの外部に置き、リポジトリの懸念がそれらから泡立たないようにする必要がありました(つまり、リポジトリを使用するコードは、内部でNHibernateを使用していることを知る必要はなく、そうする必要もありません) NHibernate のセッション管理について知っている必要があります)。私の場合、開発者がトランザクションを忘れないように、デフォルトでトランザクションが作成されることが決定されたため、読み取り専用のエスケープ メカニズムが必要でした。NHibernate ISession インスタンス ストアを内部に持つ Unit of Work パターンを使用しました。呼び出しコード (UoW 用の DSL インターフェイスも作成しました) は次のようになります。

using (var uow = UoW.Start().ReadOnly().WithHttpContext()
       .InNewScope().WithScopeContext(ScopeContextProvider.For<CRMModel>())
{
    // Repository access
}

実際にUoW.Start()は、すでに利用可能なコンテキストの量に応じて、それは短くなる可能性があります. この部分は、当然のことながら、この場合HttpContextは UoW の保存場所を指します。HttpContextおっしゃったように、ASP .NET アプリケーションの場合、HttpContext物を格納するのに最も安全な場所です。ScopeContextProvider基本的に、UoW に適切なデータ コンテキストが提供されていることを確認します (適切なデータベース/サーバーへの ISession インスタンス、その他の設定)。「ScopeContext」の概念により、「テスト」スコープ コンテキストの挿入も簡単になります。

このルートに進むと、リポジトリが明示的に UoW インターフェイスに依存するようになります。実際、抽象化できるかもしれませんが、メリットがあるかどうかはわかりません。つまり、各リポジトリ メソッドは現在の UoW インスタンスを取得し、ISession オブジェクト (または NHibernate を使用しないメソッドの場合は単純に SqlConnection) を取り出して、NHibernate クエリ/操作を実行します。CRUD を実行する必要があるメソッドに対して、現在の UoW が読み取り専用ではないことを確認するのに理想的な時期でもあるため、これは私にとってはうまくいきます。

全体として、これはあなたのすべてのポイントを解決する1つのアプローチだと思います:

  • セッション管理をリポジトリの外部にすることができます
  • ISession コンテキストは、テスト環境のコンテキスト プロバイダーでモックまたはポイントできます
  • 不必要なトランザクションを回避します (まあ、私がしたことを逆にして、.Transactional()電話か何かをする必要があります)
  • それはNHibernateの問題であるため、SQLiteでテストできなかった理由がわかりません
  • 私は Fluent NHibernate を自分で使用しています
  • リポジトリがホスト環境を無視できるようにします (つまり、リポジトリの呼び出し元が UoW ストレージ コンテキストを制御します)。

UoW の実装に関しては、始める前にもっと調べていなかったことに部分的に反省しています。machine.uowというプロジェクトがありますが、これはかなり人気があり、NHibernate とうまく連携していると私は理解しています。私はそれをあまりいじっていないので、自分で書いたものと同じくらいきれいにすべての要件を解決するかどうかはわかりませんが、開発時間も節約できたかもしれません.

どこが間違っていたのか、どうすれば改善できるのかについてコメントをいただけるかもしれませんが、これが少なくとも何らかの形で役立つことを願っています.

参考までに、私が使用しているソフトウェア スタックは次のとおりです。

  • ASP.NET MVC
  • NHibernate 上の Fluent NHibernate
  • 依存性注入のための Ninject
于 2009-10-20T20:41:41.903 に答える