繁体   English   中英

具有.Net Core身份的多租户DbContext的IoC DI

[英]IoC DI for multitenant DbContext with .Net Core Identity

我有.Net Core应用,并想使用.Net Core Identity为DbContext设置IoC / DI:

public class DataContext : IdentityDbContext<User, IdentityRole<int>, int, IdentityUserClaim<int>, IdentityUserRole<int>, IdentityUserLogin<int>, IdentityRoleClaim<int>, IdentityUserToken<int>>, IDataContext
{
    private readonly string _dbName;

    public DataContext(string dbName)
    {
        this._dbName = dbName;
    }

    public virtual DbSet<Container> Containers { get; set; }

    public virtual DbSet<Note> Notes { get; set; }

    public virtual DbSet<Post> Posts { get; set; }

    public virtual DbSet<Email> Emails { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(ConnectionStrings.DataContext.Replace(":dbname", this._dbName));
        base.OnConfiguring(optionsBuilder);
    }
}

接口:

public interface IDataContext
{
    DbSet<Container> Containers { get; set; }

    DbSet<Note> Notes { get; set; }

    DbSet<Post> Posts { get; set; }

    DbSet<Email> Emails { get; set; }
}

Startup.cs ,有以下一行:

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

但是该连接字符串不包含数据库名称。

我是否应该在界面中包含以下表格:AspNetUsers,AspNetRoles,...?

我想在Startup.cs编写如下内容:

services.AddScoped<IDataContext, DataContext>();

并在各处使用接口,而不是整个类。

我可以那样做吗? 我该怎么办?

当您使用实体框架的AddDbContext方法时,它将为您注册服务集合中的上下文。

 services.AddDbContext<DataContext>(ServiceLifetime.Scoped);

但是您可以像下面这样注册您的界面。

services.AddScoped(typeof(IDataContext), provider => provider.GetService<DataContext>());

然后,您可以使用该界面。 但是身份服务仍将使用具体类型。


PS:您知道存储库模式吗? 它使您可以轻松地将数据层与服务层分开。 例如,这对于单元测试很有帮助。


您的DataContext构造函数的问题在于,依赖项容器不知道如何解析构造函数中的字符串。 通常,当您在asp.net core中使用配置时,可以使用IOptions类型及其基础结构。

在启动中,您可以添加选项并进行配置。

public class DatabaseOptions
{
    public string DbName { get; set; }
}

services.AddOptions();
services.Configure<DatabaseOptions>(options => options.DbName = "myDbName");

然后,您可以将DataContext的构造函数更改为以下内容。

public DataContext(IOptions<DatabaseOptions> options)

如果您在启动时不知道配置值,则可以编写一个在中间件或操作过滤器中配置的上下文类型。

public class DbConfigurationContext
{
    public string DbName { get; set; }
}

public class DbConfigurationContextFilter : IAsyncActionFilter
{
    private readonly DbConfigurationContext _dbConfiguration;

    public DbConfigurationContextFilter(DbConfigurationContext dbConfiguration)
    {
        _dbConfiguration = dbConfiguration;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        _dbConfiguration.DbName = context.HttpContext.Request.Query["DbName"];
        await next();
    }
}


services.AddTransient<DbConfigurationContext>();
services.AddTransient<DbConfigurationContextFilter>();
services.AddMvc(setup =>
{
    setup.Filters.AddService(typeof(DbConfigurationContextFilter));
})

然后,您可以在DbConfigurationContext中解析此DbContext 当然,您也可以使用界面。

public DataContext(DbConfigurationContext configurationContext)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM