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

时间:2019-05-30 18:58:14

标签: c# asp.net-core dependency-injection repository dbcontext

我正在编写我的第一个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注入Controller中,然后调用存储库方法以将其分配给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:无法使用作用域服务   单例的“ RAFYC.MobileAppService.Models.RAFYCContext”   'RAFYC.MobileAppService.Repositories.IUserRepository'

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

1 个答案:

答案 0 :(得分:1)

AddDbContext默认情况下添加了DbContext范围,这将导致单例存储库出现问题。

  

从单例中解析作用域服务很危险。处理后续请求时,可能导致服务的状态不正确。

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

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

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