Quantcast
Channel: entityframework Discussions Rss Feed
Viewing all articles
Browse latest Browse all 1793

New Post: Multi-Tenant With Code First

$
0
0
Hello Mohamed,

I really have problems to understand some of your questions!

The usecase

Maybe you want to use that stuff differently than I am. My usecase is as follows:
  • one code first database model (with table1, table2 and table3 for example)
  • every tenant has exactly the same tables with the same columns
  • multiple tenants (with id 00000000-0000-0000-0000-00000000001 and 00000000-0000-0000-0000-00000000002 for example)
  • one database (with the name tenantDatabase for example)
Using my approach the database will look as follows:

[tenantDatabase].[00000000-0000-0000-0000-00000000001].[table1]
[tenantDatabase].[00000000-0000-0000-0000-00000000001].[table2]
[tenantDatabase].[00000000-0000-0000-0000-00000000001].[table3]
[tenantDatabase].[00000000-0000-0000-0000-00000000002].[table1]
[tenantDatabase].[00000000-0000-0000-0000-00000000002].[table2]
[tenantDatabase].[00000000-0000-0000-0000-00000000002].[table3]

Reading data of a concrete tenant

The following code instantiates the DbContext for reading data of tenant 1:
Guid tenantId = Guid.Parse("00000000-0000-0000-0000-00000000001");
using (var dbContext = TenantDataCtx.TenantDataCtx.Create("databaseServer", "tenantDatabase", "databaseUserName", "databasePassword", tenantId);
{
  // everything you do with dbContext will be executed within the schema of tenant 1
  // EXAMPLE: Read data from table1
  var dataFromTable1OfTenant1 = dbContext.Set<Table1>().ToList();
}
The following code instantiates the DbContext for reading data of tenant 2:
Guid tenantId = Guid.Parse("00000000-0000-0000-0000-00000000002");
using (var dbContext = TenantDataCtx.TenantDataCtx.Create("databaseServer", "tenantDatabase", "databaseUserName", "databasePassword", tenantId);
{
  // everything you do with dbContext will be executed within the schema of tenant 2
  // EXAMPLE: Read data from table2
  var dataFromTable2OfTenant2 = dbContext.Set<Table2>().ToList();
}

Update the tables of concrete tenants

The same approach applies for the usage of SqlServerSchemaAwareMigrationSqlGenerator.

The following code updates the tables for tenant 1 within schema 00000000-0000-0000-0000-000000000001:
Guid tenantId = Guid.Parse("00000000-0000-0000-0000-000000000001");
string schemaName = tenantId.ToString();
var tenantDataMigrationsConfiguration = new DbMigrationsConfiguration<TenantDataContext.TenantDataCtx>();
tenantDataMigrationsConfiguration.AutomaticMigrationsEnabled = false;
tenantDataMigrationsConfiguration.SetSqlGenerator("System.Data.SqlClient", new SqlServerSchemaAwareMigrationSqlGenerator(schemaName));
tenantDataMigrationsConfiguration.SetHistoryContextFactory("System.Data.SqlClient", (existingConnection, defaultSchema) => new HistoryContext(existingConnection, schemaName));
tenantDataMigrationsConfiguration.TargetDatabase = new System.Data.Entity.Infrastructure.DbConnectionInfo(connectionString, "System.Data.SqlClient");
tenantDataMigrationsConfiguration.MigrationsAssembly = typeof(TenantDataContext.TenantDataCtx).Assembly;
tenantDataMigrationsConfiguration.MigrationsNamespace = "TenantDataContext.Migrations.TenantData"; // Update that namespace to your migration namespace!!!!!!!

DbMigrator tenantDataCtxMigrator = new DbMigrator(tenantDataMigrationsConfiguration);
tenantDataCtxMigrator.Update();
The following code updates the tables for tenant 2 within schema 00000000-0000-0000-0000-000000000002:
Guid tenantId = Guid.Parse("00000000-0000-0000-0000-000000000002");
string schemaName = tenantId.ToString();
var tenantDataMigrationsConfiguration = new DbMigrationsConfiguration<TenantDataContext.TenantDataCtx>();
tenantDataMigrationsConfiguration.AutomaticMigrationsEnabled = false;
tenantDataMigrationsConfiguration.SetSqlGenerator("System.Data.SqlClient", new SqlServerSchemaAwareMigrationSqlGenerator(schemaName));
tenantDataMigrationsConfiguration.SetHistoryContextFactory("System.Data.SqlClient", (existingConnection, defaultSchema) => new HistoryContext(existingConnection, schemaName));
tenantDataMigrationsConfiguration.TargetDatabase = new System.Data.Entity.Infrastructure.DbConnectionInfo(connectionString, "System.Data.SqlClient");
tenantDataMigrationsConfiguration.MigrationsAssembly = typeof(TenantDataContext.TenantDataCtx).Assembly;
tenantDataMigrationsConfiguration.MigrationsNamespace = "TenantDataContext.Migrations.TenantData"; // Update that namespace to your migration namespace!!!!!!!

DbMigrator tenantDataCtxMigrator = new DbMigrator(tenantDataMigrationsConfiguration);
tenantDataCtxMigrator.Update();
If you want to have a different tables/columns per tenant than you have to design the database model for every tenant and you have to create migrations separately for every tenant. I think migrations are not well suited for that usecase.

Your question about data loss is a different problem and has nothing to do with the multi-tenancy.

Regards,

Tobias

Viewing all articles
Browse latest Browse all 1793

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>