2

多租户的DbContext我对.NET核心应用程序,并要设置的IoC/DI为的DbContext与.net核心身份:的IoC DI用于.NET核心身份

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

而且使用的界面,而不是到处全班。

我可以这样做吗?我该怎么做?

回答

3

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

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

但是你可以注册你的界面,如下所示。

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

然后你可以使用接口。但身份服务仍将使用具体类型。你知道吗repository pattern?它使您能够轻松地从服务层分离数据层。这对单元测试有很大的帮助。


的问题与您DataContext构造函数是依赖容器不知道如何解决在构造函数的字符串。通常,当您使用asp.net核心中的配置时,您可以使用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)); 
}) 

然后你可以在你的DbContext解决此DbConfigurationContext。你也可以使用界面。

public DataContext(DbConfigurationContext configurationContext) 
+0

他必须使用UoW Pattern注册,就像你说的那样。 – Valkyrie

+0

当我将该行插入'Startup.cs'时,我有500个错误,如果你给我写一个存储库模式和示例的链接,我将不胜感激。 –

+0

@ A.Gladkiy我编辑了我的文章。你需要两条线。我会考虑将DbContext注册为范围。 – NtFreX