私は 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