按租户模式应用EF Core迁移。

问题描述 投票:1回答:1

我正在使用.NET Core 3.1和EntityFramework Core 3.1.3.我试图使用DB模式实现租户数据分离。我已经阅读了 这个. 我知道这有点过时了,所以我调整了一下。

我已经创建了一个DbContext的实现。

public class AppDataContext : DbContext
{
    private readonly ITenantProvider _tenantProvider;

    public AppDataContext(DbContextOptions<AppDataContext> options, ITenantProvider tenantProvider) : base(options)
    {
        _tenantProvider = tenantProvider;
    }

    public DbSet<Book> Books { get; set; }
    public DbSet<Comics> Comics { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Tenant schema mapping
        var tenant = _tenantProvider.GetTenantString();
        modelBuilder.HasDefaultSchema(tenant);
    }

    public static void ApplyMigrations(string connectionString, string tenant)
    {
        var optionsBuilder = new DbContextOptionsBuilder<AppDataContext>();
        optionsBuilder.UseSqlServer(connectionString, x => x.MigrationsHistoryTable("__EFMigrationsHistory", tenant));
        var ctx = new AppDataContext(optionsBuilder.Options, StaticTenantProvider.WithTenant(tenant));

        ctx.Database.Migrate();
    }
}

ITenantProvider是一个在.NET Core DI中注册的scoped服务。这个AppDataContext是这样注册的。

services.AddDbContext<AppDataContext>((ctx, opt) =>
{
   opt.UseSqlServer(Configuration["SqlConnectionString"]);
});

现在,我的想法是,无论何时我想提供另一个租户,我都会像这样调用(数据库实例已经存在,并且可能已经有了一些tableschemas)。

var connString = GetConnString();       // Where does connection string and tenant name come from is not important
var tenantName = GetTenantName();
AppDataContext.ApplyMigrations(connString, tenantName);

在这之后,我就会有一个新的独特的数据库模式 所有的表都为租户设置好了。

不幸的是,这并不奏效。表仍然在为默认的 "dbo "模式创建(我使用SqlServer)。

我开始在互联网上寻找,首先我找到了 这个. 我觉得有点奇怪,但还是试了一下。

public static void ApplyMigrations(string connectionString, string tenant)
{
    var optionsBuilder = new DbContextOptionsBuilder<AppDataContext>();
    optionsBuilder.UseSqlServer(connectionString);
    var ctx = new AppDataContext(optionsBuilder.Options, StaticTenantProvider.WithTenant(tenant));

    var command = $"IF (NOT EXISTS (SELECT * FROM sys.schemas WHERE name = N'{tenant}')) " +
                  "BEGIN" +
                  $"  EXEC ('CREATE SCHEMA {tenant}');" +
                  "END";
    ctx.Database.ExecuteSqlRaw(command);
    ctx.Database.Migrate();
}

没用。我可以看到模式被创建了(使用SSMS),但是表仍然在 "dbo "中。

然后我想,也许它在定位Migration History表的时候出了问题,所以我尝试了MigrationsHistoryTable,就像这样。

optionsBuilder.UseSqlServer(connectionString, x => x.MigrationsHistoryTable("__EFMigrationsHistory", tenant));

但是没有,Migration History表确实在新的模式中被创建了,但是其他的表还是在 "dbo "中。

我到底漏掉了什么?或者说,也许不可能同时使用EF Migrations和Schema分离?

先谢谢你了。

EDIT: 要说明的是:我使用的是代码优先的方法。已经为AppDataContext生成了迁移。

c# sql-server .net-core entity-framework-core ef-migrations
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.