在ASP.NET Core中的通用存储库没有在Startup.cs中每个表单独的AddScoped行? [英] Generic repository in ASP.NET Core without having a separate AddScoped line per table in Startup.cs?

查看:439
本文介绍了在ASP.NET Core中的通用存储库没有在Startup.cs中每个表单独的AddScoped行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目中有一个通用的存储库。
请考虑以下控制器片段:

$ b

  public class Lookup1Controller:Controller 
{
readonly MyDbContext _db;

public Lookup1Controller(MyDbContext dataContext)
{
_db = dataContext;
}

公共异步任务< 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;
}

公共异步任务< IActionResult> Index()
{
var lookup1s = await _repository.SelectAll();

return View(lookup1s);
}

}

NET 5最佳实践,从我读的。
,但如果我在浏览器中访问该控制器路由,我将得到以下错误:

  InvalidOperationException:尝试激活MyProject.Controllers.Lookup1时,无法解析类型为MyProject.Data.IGenericRepository`1 [MyProject.Models.Lookup1]的服务。 

因为我没有注入GenericRepository来使用接口。



添加到我的 Startup.cs an AddScoped ConfigureServices 方法中的表
$ b

  services .AddScoped< IGenericRepository< Lookup1>,&GenericRepository LT; Lookup1>> (); 
services.AddScoped< IGenericRepository< Lookup2>,GenericRepository< Lookup2>> ();
services.AddScoped< IGenericRepository< Lookup3>,GenericRepository< Lookup3>> ();
services.AddScoped< IGenericRepository< Lookup4>,GenericRepository< Lookup4>> ();

这样我的代码就能运行而不会引发异常。



然而我的数据库有大约100个简单的查询表。当我查看上面100行代码时,它看起来不太合适。



感觉就像复制和粘贴代码。每次我通过添加一个新的模型和控制器来添加一个新的表格时,我的代码将被编译而不会给我一个错误。但是,如果我运行程序并转到该视图,如果忘记将AddScoped行添加到我的 Startup.cs 中,我可能会遇到控制器运行错误。



我的问题:


  1. 对于 Startup.cs ConfigureServices 方法中的每个查找表,最好有一个services.AddScoped。 ? 它是一个通用的存储库,所以没有办法在一行中写入100个复制和粘贴行吗?

  2. >
  3. 如果不是,那么使用我的代码来做到这一点的最佳做法是什么?

  4. =h2_lin>解决方案

只需使用非泛型注册重载(需要传递2 Type 对象的那些重载)。提供您的界面的打开通用类型执行:

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

在您的控制器中为特定类型的存储库添加依赖项(一种封闭的泛型类型) p>

  public HomeController(IGenericRepository< Lookup1>存储库)
{
...
}


I have a generic repository in my project. Consider the following controller snippet

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

I don't see the need to have my Database reference both in my Generic repository as well as each of my controllers.

I refactor it to:

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

}

which is much neater and ASP.NET 5 best practice from what I read. but I will get the following error if I access that controller route in my browser:

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

because of I haven't injected the GenericRepository to use the interface.

I add to my Startup.cs an AddScoped line for each and every of my tables in the ConfigureServices method

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

so that my code runs without throwing an exception.

However my database has about 100 simple lookup tables. When I look at the above 100 lines of code it just doesn't look right.

It feels like copy and paste code. Each time I add a new table by adding a new model and controller with view my code will compile without giving me an error. But if I run the program and go to that view I could get the controller run error if I forgot to add the AddScoped line to my Startup.cs. Not really good for maintainability.

My question:

  1. Is it really best practice to have a services.AddScoped for each and every lookup table in the ConfigureServices method of Startup.cs?

  2. It is a generic repository so isn't there be a way to write those 100 copy and paste lines in one line?

  3. If not then what is the best practice way to do this using my code?

解决方案

Just use the non-generic registration overloads (The ones where you need to pass the 2 Type objects.) Then provide the open generic types of both your interface and the implementation:

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

In your controller add a dependency for a repository of a specific type (a closed generic type)

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

这篇关于在ASP.NET Core中的通用存储库没有在Startup.cs中每个表单独的AddScoped行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆