EF core и ASP. NET Core с поддержкой мультитенюса на основе схемы. - PullRequest
2 голосов
/ 01 апреля 2020

Я строю и приложение с ASP. NET ядро ​​и EF ядро. Я хочу реализовать многопользовательскую схему на основе одной базы данных. Каждая схема в моей базе данных будет состоять из одного и того же набора таблиц с одинаковыми именами, поэтому все схемы имеют одинаковую структуру. Но имена схем заранее неизвестны, так как я хочу создать их динамически в моем приложении.

Я прочитал эту статью блога , где автор представляет метод, использующий IDbCommandInterceptor , но изменение SQL таким способом может привести к множеству проблем, таких как проблемы безопасности или невозможность выполнения запросов.

Как динамически указать в DBContext, какую схему использовать (в зависимости от полученный запрос), чтобы данные сохранялись и извлекались из указанной схемы?

1 Ответ

2 голосов
/ 01 апреля 2020

Сводка:

Это можно сделать через .HasDefaultSchema () и некоторые настройки конфигурации в вашем контексте.

Вы можете увидеть пример на GitHub.com .


Что там делается:

1) Мы добавляем схему в app.settings:

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

2) Дополнительная модель и поставщик для схемы:

DatabaseSettings.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

        ...
    }
}

Что не сделано?

  • Это чисто Po C, поэтому его нельзя использовать в качестве готового к работе кода и требует обширного тестирования / профилирования.

  • Это не проверяется в app.settings изменение конфигурации «на лету» и загрузка пользовательской конфигурации могут вызывать различные проблемы.

  • Миграции выполняются человеком исправлено использование пользовательской схемы. Возможно, это возможно для поддержки автоматических c миграций в выбранную схему во время выполнения, см. эту ссылку , но я никогда не пробовал.

...