Multi-Tenant With Code First EF6

后端 未结 4 1895
小鲜肉
小鲜肉 2020-11-27 13:55

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

4条回答
  •  时光说笑
    2020-11-27 14:32

    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; }
        }
    }
    

提交回复
热议问题