如何将范围服务注入DbContext?净核心

时间:2018-02-08 23:50:26

标签: c# asp.net-core .net-core entity-framework-core

我正在构建多租户应用,并试图让数据安全性正常运行。 Context的单元测试工作得很好,因为我用options和UserContext创建了上下文,但是我很难让它在程序集中工作,因为它需要注入userContext。

我无法使用标准控制器注入,就像我拥有它一样,上下文创建失败:

services.AddEntityFrameworkNpgsql()
                .AddDbContext<MultiTenantContext>(o =>
                    o.UseNpgsql(Configuration.GetConnectionString("DbContext")

我不能或者我不知道如何以这种方式注入我的UserContext ......

3 个答案:

答案 0 :(得分:6)

简单使用构造函数注入。它的工作方式与控制器相同。

public class MultiTenantContext : DbContext
{
    private UserContext _userContext;

    public MultiTenantContext(DbContextOptions options, UserContext userContext) : base(options)
    {
        _userContext = userContext;
    }
}

您需要确保在注册实体框架之前注册UserContext服务。即克。

services.AddScoped<UserContext, UserContext>();
services.AddEntityFrameworkNpgsql()
                .AddDbContext<MultiTenantContext>(o =>
                    o.UseNpgsql(Configuration.GetConnectionString("DbContext")

答案 1 :(得分:3)

我假设您在多租户应用程序中尝试根据来自HttpRequest的登录用户找出Tenant。你可以做这样的事情

public class UserContext
{
    private readonly IHttpContextAccessor _accessor;
    public RequestContextAdapter(IHttpContextAccessor accessor)
    {
        this._accessor = accessor;
    }

    public string UserID
    {
        get
        {
            // you have access to HttpRequest object here
            //this._accessor.HttpContext.Request
        }
    }
}

ASP.NET Core会自动将IHttpContextAccessor注入UserContext

您还必须注册UserContext

services.AddScoped<UserContext, UserContext>();

然后使用构造函数注入在任何需要的地方注入UserContext

答案 2 :(得分:0)

被接受的答案对我也不起作用,我最终采取了与原始答案非常相似的方法,感谢@Christian的指导。

我想将服务注入到DbContext中,该服务负责根据以下HTTP请求标头动态加载连接字符串,以下是使用的代码

在启动中:

  services.AddScoped<IConnectionService, ConnectionService>();
  services.AddDbContext<MyDbContext>(); //Connection string will be set on event OnConfiguring

在MyDbContext中:

public class MyDbContext : DbContext
    {
        private readonly IConnectionService _connectionService;

        public MyDbContext(DbContextOptions<MyDbContext> options, IConnectionService connectionService) : base(options)
        {
            _connectionService = connectionService;
        }

        public DbSet<Customer> Customers { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            var connectionString = _companyConnectionService.ConnectionString; //Custom logic to read from http request header certain value and switch connection string
            optionsBuilder.UseSqlServer(connectionString);
        }
    }

希望这会有所帮助。