Our organization has need to have a single database, multi-tenant
(by table schema, not by tenant id) architecture.
There is a great article h
Thanks to: Tobias! You save me a years...
My modification for Oracle DB under EF 6:
public class IntegrationDbContext : DbContext, IDbModelCacheKeyProvider
{
private static readonly ILog __log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
///
/// Factory method
///
public static IntegrationDbContext Create(string connectionStringName)
{
return new IntegrationDbContext(connectionStringName, GetDBSchema(connectionStringName));
}
///
/// Constructor
///
public IntegrationDbContext()
{
Database.SetInitializer(null);
}
///
/// Constructor
///
internal IntegrationDbContext(string connectionString, string schemaName)
: base("name={0}".Fill(connectionString))
{
Database.SetInitializer(null);
SchemaName = schemaName;
}
///
/// DB schema name
///
public string SchemaName { get; private set; }
#region Tables
///
/// Integration table "SYNC_BONUS_DISTRIBUTION"
///
public virtual DbSet SYNC_BONUS_DISTRIBUTION { get; set; }
///
/// Integration table "SYNC_MESSAGE_DISTRIBUTION"
///
public virtual DbSet SYNC_MESSAGE_DISTRIBUTION { get; set; }
///
/// Integration table "IMPORT_TEMPLATES"
///
public virtual DbSet IMPORT_TEMPLATES { get; set; }
#endregion //Tables
private static Dictionary __schemaCache = new Dictionary();
private static object __schCacheLock = new object();
///
/// Gets DB schema name from connection string, or default from config
///
private static string GetDBSchema(string connectionStringName)
{
string result;
if (!__schemaCache.TryGetValue(connectionStringName, out result))
{
lock (__schCacheLock)
{
if (!__schemaCache.TryGetValue(connectionStringName, out result))
{
DbConnectionStringBuilder builder = new DbConnectionStringBuilder();
builder.ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
result = builder.ContainsKey("User ID") ? builder["User ID"] as string : ConfigurationManager.AppSettings["DefaultIntegrationSchema"];
__schemaCache.Add(connectionStringName, result);
}
}
}
return result;
}
///
/// Context initialization
///
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
__log.DebugFormat("OnModelCreating for integration model in schema: {0}", SchemaName);
if (SchemaName != null)
{
modelBuilder.HasDefaultSchema(SchemaName);
}
//### CLOB settings
modelBuilder.Properties().Where(p => p.PropertyType == typeof(string) &&
p.GetCustomAttributes(typeof(MaxLengthAttribute), false).Length == 0)
.Configure(p => p.HasMaxLength(2000));
base.OnModelCreating(modelBuilder);
}
///
/// Implementation of - thanks by this is 'OnModelCreating' calling for each specific schema.
///
public string CacheKey
{
get { return SchemaName; }
}
}