1. ホーム
  2. generics

Startup.csでテーブルごとに個別のAddScoped行を持たずにASP.NET Coreで一般的なリポジトリ?

2023-08-24 17:42:58

質問

私のプロジェクトでは、一般的なリポジトリを持っています。 次のようなコントローラのスニペットを考えてみましょう。

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リポジトリと各コントローラの両方にDatabaseの参照を持つ必要はないように思います。

私はそれをリファクタリングします。

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.csAddScoped の行で、それぞれのテーブルに対して 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行のコードを見たとき、それは正しく見えません。

それはコピーアンドペーストコードのように感じます。新しいテーブルを追加するたびに、新しいモデルとビューを持つコントローラを追加することで、私のコードはエラーを出さずにコンパイルされます。しかし、プログラムを実行し、そのビューに移動すると、AddScoped 行を Startup.cs . メンテナンス性にはあまりよくありません。

私の質問です。

  1. の各ルックアップテーブルに services.AddScoped を設定することは、本当にベストプラクティスなのでしょうか? ConfigureServices メソッドの Startup.cs ?

  2. 汎用リポジトリなので、100行のコピペを1行で書く方法はないのでしょうか?

  3. そうでない場合、私のコードを使用してこれを行うためのベストプラクティスの方法は何ですか?

どのように解決するのですか?

一般的でない登録のオーバーロードを使用すればよいのです(2つの Type オブジェクトを渡す必要があります)。そして オープンジェネリックタイプ を提供します。

services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));

コントローラで、特定のタイプ(クローズドジェネリックタイプ)のリポジトリに対する依存関係を追加します。

public HomeController(IGenericRepository<Lookup1> repository)
{
    ...
}