私のプロジェクトには一般的なリポジトリがあります。次のコントローラースニペットを検討してください
public class Lookup1Controller : Controller
{
readonly MyDbContext _db;
public Lookup1Controller(MyDbContext dataContext)
{
_db = dataContext;
}
public async Task<IActionResult> Index()
{
IGenericRepository<Lookup1> _repository = new GenericRepository<Lookup1>(_db);
var lookup1s = await _repository.SelectAll();
return View(lookup1s);
}
Genericレポジトリと各コントローラーの両方でデータベース参照を持つ必要はありません。
私はそれをリファクタリングします:
public class Lookup1Controller : Controller
{
private IGenericRepository<Lookup1> _repository;
public Lookup1Controller(IGenericRepository<Lookup1> repository)
{
_repository = repository;
}
public async Task<IActionResult> Index()
{
var lookup1s = await _repository.SelectAll();
return View(lookup1s);
}
}
私が読んだことから、これは非常にすてきでASP.NET 5のベストプラクティスです。しかし、ブラウザでそのコントローラールートにアクセスすると、次のエラーが表示されます。
InvalidOperationException: Unable to resolve service for type 'MyProject.Data.IGenericRepository`1[MyProject.Models.Lookup1]' while attempting to activate 'MyProject.Controllers.Lookup1.
インターフェイスを使用するためにGenericRepositoryを挿入していないためです。
Startup.cs
にAddScoped
メソッドの各テーブルのConfigureServices
行を追加します
services.AddScoped<IGenericRepository<Lookup1>,GenericRepository<Lookup1>> ();
services.AddScoped<IGenericRepository<Lookup2>,GenericRepository<Lookup2>> ();
services.AddScoped<IGenericRepository<Lookup3>,GenericRepository<Lookup3>> ();
services.AddScoped<IGenericRepository<Lookup4>,GenericRepository<Lookup4>> ();
etc
例外をスローせずにコードが実行されるようにします。
ただし、私のデータベースには約100個の単純なルックアップテーブルがあります。上記の100行のコードを見ると、正しく見えません。
コードをコピーして貼り付けるような感じです。ビューで新しいモデルとコントローラーを追加して新しいテーブルを追加するたびに、エラーが発生せずにコードがコンパイルされます。しかし、プログラムを実行してそのビューに移動すると、Startup.cs
にAddScoped行を追加するのを忘れた場合、コントローラーの実行エラーが発生する可能性があります。保守性にはあまり良くありません。
私の質問:
Startup.cs
のConfigureServices
メソッドのすべてのルックアップテーブルにservices.AddScopedを設定することは本当にベストプラクティスですか?
これは汎用リポジトリなので、これらの100行を1行でコピーして貼り付ける方法はありませんか?
そうでない場合、私のコードを使用してこれを行うためのベストプラクティスの方法は何ですか?
非ジェネリック登録オーバーロード(2つのType
オブジェクトを渡す必要があるオーバーロード)を使用します。次に、インターフェイスと実装の両方の open generic types を指定します。
services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
コントローラーで、特定のタイプ(閉じた汎用タイプ)のリポジトリーの依存関係を追加します
public HomeController(IGenericRepository<Lookup1> repository)
{
...
}