web-dev-qa-db-fra.com

Référentiel générique dans ASP.NET Core sans avoir une ligne AddScoped distincte par table dans Startup.cs?

J'ai un référentiel générique dans mon projet. Considérez l'extrait de contrôleur suivant

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);
    }

Je ne vois pas la nécessité d'avoir ma référence de base de données à la fois dans mon référentiel générique ainsi que dans chacun de mes contrôleurs.

Je le refactorise pour:

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);
    }

}

ce qui est beaucoup plus propre et les meilleures pratiques d'ASP.NET 5 d'après ce que j'ai lu. mais j'obtiendrai l'erreur suivante si j'accède à cette route de contrôleur dans mon navigateur:

InvalidOperationException: Unable to resolve service for type 'MyProject.Data.IGenericRepository`1[MyProject.Models.Lookup1]' while attempting to activate 'MyProject.Controllers.Lookup1.

car je n'ai pas injecté le GenericRepository pour utiliser l'interface.

J'ajoute à mon Startup.cs une ligne AddScoped pour chacune de mes tables dans la méthode 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

afin que mon code s'exécute sans lever d'exception.

Cependant, ma base de données contient environ 100 tables de recherche simples. Quand je regarde les 100 lignes de code ci-dessus, cela ne semble pas juste.

Cela ressemble à copier et coller du code. Chaque fois que j'ajoute une nouvelle table en ajoutant un nouveau modèle et contrôleur avec vue mon code se compilera sans me donner d'erreur. Mais si j'exécute le programme et accède à cette vue, je pourrais obtenir l'erreur d'exécution du contrôleur si j'oublie d'ajouter la ligne AddScoped à mon Startup.cs. Pas vraiment bon pour la maintenabilité.

Ma question:

  1. Est-il vraiment préférable d'avoir un service.AddScoped pour chaque table de recherche dans la méthode ConfigureServices de Startup.cs?

  2. Il s'agit d'un référentiel générique, donc n'y a-t-il pas moyen d'écrire ces 100 lignes de copier-coller sur une seule ligne?

  3. Si ce n'est pas le cas, quelle est la meilleure façon de procéder en utilisant mon code?

47
dfmetro

Utilisez simplement les surcharges d'enregistrement non génériques (celles où vous devez passer les 2 Type objets.) Ensuite, fournissez les types génériques ouverts de votre interface et de l'implémentation:

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

Dans votre contrôleur, ajoutez une dépendance pour un référentiel d'un type spécifique (un type générique fermé)

public HomeController(IGenericRepository<Lookup1> repository)
{
    ...
}
84
Daniel J.G.