Database Schema not changing at Runtime in Asp.net Core 2.2 & Entity Framework Core

asp.net asp.net-core asp.net-mvc c# entity-framework-core

Question

i had an application where data is saved in different sql schema for different Users.

For e.g.

User 1 Data is saved in SCHEMA1

User 2 Data is saved in SCHEMA2

Previously application was developed in MVC 3 and it is working fine and as expected. Now we are migrating application in .Net Core 2.2 in which this fucntionality is not working
.net core does not have IDbModelCacheKeyProvider due to this only one schema is working

Below is the DBContext File

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    //public string Schema { get; set; }
    private readonly IConfiguration configuration;
    public string SchemaName { get; set; }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {

    }

    public ApplicationDbContext(string schemaname)
        : base()
    {
        SchemaName = schemaname;
    }

    public DbSet<EmployeeDetail> EmployeeDetail { get; set; }



    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
                      .AddJsonFile("appsettings.json");
        var configuration = builder.Build();

        optionsBuilder.UseSqlServer(configuration["ConnectionStrings:SchemaDBConnection"]);

        var serviceProvider = new ServiceCollection().AddEntityFrameworkSqlServer()
                            .AddTransient<IModelCustomizer, SchemaContextCustomize>()
                            .BuildServiceProvider();
    }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.RemovePluralizingTableNameConvention();
        modelBuilder.HasDefaultSchema(SchemaName);
        base.OnModelCreating(modelBuilder);
    }

    public string CacheKey
    {
        get { return SchemaName; }
    }


}   


public class SchemaContextCustomize : ModelCustomizer
{
    public SchemaContextCustomize(ModelCustomizerDependencies dependencies)
        : base(dependencies)
    {

    }
    public override void Customize(ModelBuilder modelBuilder, DbContext dbContext)
    {
        base.Customize(modelBuilder, dbContext);

        string schemaName = (dbContext as ApplicationDbContext).SchemaName;
        (dbContext as ApplicationDbContext).SchemaName = schemaName;

    }
}

My question is how to change schemaName at runtime

So what is the right way to organize that mechanism:

Figure out the schema name by the user credentials; Get user-specific data from database from specific schema.

1
2
6/20/2019 10:06:31 AM

Accepted Answer

I was able to change schema at runtime by changing onConfiguring Method

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{

    public string SchemaName { get; set; }


    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {

    }

    public ApplicationDbContext(string schemaname)
        : base()
    {
        SchemaName = schemaname;
    }

    public DbSet<EmployeeDetail> EmployeeDetail { get; set; }



    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {

        var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
                      .AddJsonFile("appsettings.json");
        var configuration = builder.Build();

        var serviceProvider = new ServiceCollection().AddEntityFrameworkSqlServer()
                            .AddSingleton<IModelCustomizer, SchemaContextCustomize>()
                            .BuildServiceProvider();
        optionsBuilder.UseSqlServer(configuration["ConnectionStrings:SchemaDBConnection"]).UseInternalServiceProvider(serviceProvider);
    }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
       // modelBuilder.MapProduct(SchemaName);

        modelBuilder.RemovePluralizingTableNameConvention();
        if (!string.IsNullOrEmpty(SchemaName))
        {
            modelBuilder.HasDefaultSchema(SchemaName);
        }
        base.OnModelCreating(modelBuilder);
    }

    public string CacheKey
    {
        get { return SchemaName; }
    }
public class SchemaContextCustomize : ModelCustomizer
{
    public SchemaContextCustomize(ModelCustomizerDependencies dependencies)
        : base(dependencies)
    {

    }
    public override void Customize(ModelBuilder modelBuilder, DbContext dbContext)
    {
        base.Customize(modelBuilder, dbContext);

        string schemaName = (dbContext as ApplicationDbContext).SchemaName;
        (dbContext as ApplicationDbContext).SchemaName = schemaName;

    }
}
}
2
6/26/2019 9:44:47 AM

Popular Answer

The best way is to use Multi-Tenancy Architecture to be able to use database schema per user ( Tenant )
This architecture is recommended for Saas appllications

enter image description here


Concepts

Let’s agree on some basic concepts:



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow