2

我正在使用 ASP.NET 核心和 EF 核心构建和应用程序。我想使用单个数据库实现基于模式的多租户。我的数据库中的每个模式都将包含相同名称的同一组表,因此所有模式共享相同的结构。但是模式名称事先并不知道,因为我想在我的 APP 中动态创建它们。

我读了这篇博文,作者介绍了一种使用 IDbCommandInterceptor的方法,但是以这种方式修改 SQL 可能会带来很多问题,例如安全问题或使请求失败。

如何在 DBContext 中动态指定要使用的模式(基于收到的请求),以便从这个指定的模式中保存和检索数据?

4

1 回答 1

2

概括:

这可以通过 .HasDefaultSchema() 和您的上下文中的一些配置注入来完成。

您可以在 GitHub.com 上查看示例。


那里做了什么:

1)我们将架构添加到app.settings:

  "Database": {
    "Schema": "test"
  },

2)模式的附加模型和提供者:

数据库设置.cs

public class DatabaseSettings
{
    public string Schema { get; set; }
}

SchemaProvider.cs

public class SchemaProvider : ISchemaProvider
{
    private DatabaseSettings Settings { get; }

    public SchemaProvider(IOptions<DatabaseSettings> settings)
    {
        this.Settings = settings.Value;
    }

    public string GetSchema()
    {
        return this.Settings.Schema;
    }
}

3)在Startup.cs我们为模式名称注册新的配置模型和提供者:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<DatabaseSettings>(this.Configuration.GetSection("Database"));
    services.Add(new ServiceDescriptor(typeof(ISchemaProvider), typeof(SchemaProvider), ServiceLifetime.Scoped));

    var connection = this.Configuration.GetConnectionString("TestDatabase");
    services.AddDbContext<TestContext>(options => options.UseSqlServer(connection));

    services.AddControllers();
}

4)在TestContext(EF Core Context)中,我们添加模式提供者的注入并应用选定的模式:

public partial class TestContext : DbContext
{
    private ISchemaProvider SchemaProvider { get; }

    ...

    public TestContext(DbContextOptions<TestContext> options, ISchemaProvider schemaProvider)
        : base(options)
    {
        this.SchemaProvider = schemaProvider;
    }

    ...

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema(this.SchemaProvider?.GetSchema() ?? "dbo"); // null value supported for migrations from EF Core CLI without application context

        ...
    }
}

什么没有做?

  • 这纯粹是 PoC,因此不能用作生产就绪代码,需要大量测试/分析。

  • 这没有针对 app.settings 即时更改和自定义配置加载进行测试,可能存在不同的问题。

  • 手动修复迁移以使用自定义架构。可能支持自动迁移到运行时选择的模式,请参阅此链接,但我从未尝试过。

于 2020-04-01T11:11:53.007 回答