如何将 DbContext 注入 ASP.NET 核心中的存储库构造函数

How to inject DbContext into repository constructor in ASP.NET core

我正在编写我的第一个 ASP.NET Core Web API 并且正在尝试弄清楚如何将我的 DbContext 对象注入到我的存储库构造函数中。我遵循了此 tutorial 的 EF 部分,其中 DbContext 通过 services.AddDbContext<DbContext> 注册到服务集合,services.GetRequiredService<DbContext>() 用于初始化数据库值。

    public class Startup
    {

        public IConfiguration Configuration { 

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddSingleton<IItemRepository, ItemRepository>();
            services.AddSingleton<IUserRepository, UserRepository>();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
            });

            services.AddDbContext<RAFYCContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            //CreateWebHostBuilder(args).Build().Run();

            IWebHost host = CreateWebHostBuilder(args).Build();

            using (IServiceScope scope = host.Services.CreateScope())
            {
                IServiceProvider services = scope.ServiceProvider;
                try
                {
                    RAFYCContext context = services.GetRequiredService<RAFYCContext>();
                    DbInitializer.Initialize(context);
                }
                catch (Exception ex)
                {
                    ILogger logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred while seeding the database.");
                }
            }

            host.Run();
        }
    }

我能够将 DbContext 注入控制器,然后调用存储库方法将其分配给 UserRepository:

    public class UserController : ControllerBase
    {
        IUserRepository _userRepo;

        public UserController(IUserRepository userRepo, RAFYCContext context)
        {
            _userRepo = userRepo;
            _userRepo.SetDbContext(context);
        }
    }
    public class UserRepository : IUserRepository
    {
        public RAFYCContext _context;

        public UserRepository() { }

        public void SetDbContext(RAFYCContext context)
        {
            this._context = context;
        }
    }

这可行,但是我想将 DbContext 注入到我的存储库的构造函数中,而不是在实例化后在 Controller 构造函数中分配它,如下所示:

    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        IUserRepository _userRepo;

        public UserController(IUserRepository userRepo)
        {
            _userRepo = userRepo;
        }
    }
    public class UserRepository : IUserRepository
    {
        RAFYCContext _context;

        public UserRepository(RAFYCContext context)
        {
            _context = context;
        }
    }

使用此代码我得到以下错误:

InvalidOperationException: Cannot consume scoped service 'RAFYC.MobileAppService.Models.RAFYCContext' from singleton 'RAFYC.MobileAppService.Repositories.IUserRepository'

有人知道 ASP.NET Core (2.2) 是否可行吗?

AddDbContext 默认添加一个 DbContext 范围,这会导致单例存储库出现问题。

It's dangerous to resolve a scoped service from a singleton. It may cause the service to have incorrect state when processing subsequent requests.

引用Dependency injection in ASP.NET Core: Service lifetimes

如果可能的话,我建议添加存储库。

services.AddScoped<IItemRepository, ItemRepository>();
services.AddScoped<IUserRepository, UserRepository>();