Remove DbConfig and new constructors on DbContextBase and refactor Migrations to use explcit generation of IOqtaneDatabase instance

This commit is contained in:
Charles Nurse 2021-05-12 15:17:40 -07:00
parent c958f90ee2
commit c036a9d11f
34 changed files with 137 additions and 225 deletions

View File

@ -11,7 +11,6 @@
@inject IInstallationService InstallationService @inject IInstallationService InstallationService
@inject IDatabaseService DatabaseService @inject IDatabaseService DatabaseService
@inject IStringLocalizer<Add> Localizer @inject IStringLocalizer<Add> Localizer
@inject IEnumerable<IOqtaneDatabase> Databases
@if (_tenants == null) @if (_tenants == null)
{ {

View File

@ -5,6 +5,6 @@ namespace Oqtane.Repository.Databases.Interfaces
{ {
public interface IMultiDatabase public interface IMultiDatabase
{ {
public IEnumerable<IOqtaneDatabase> Databases { get; } public IOqtaneDatabase ActiveDatabase { get; }
} }
} }

View File

@ -14,16 +14,5 @@ namespace Oqtane.Extensions
return optionsBuilder; return optionsBuilder;
} }
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string databaseType, string connectionString)
{
var type = Type.GetType(databaseType);
var database = Activator.CreateInstance(type) as IOqtaneDatabase;
database.UseDatabase(optionsBuilder, connectionString);
return optionsBuilder;
}
} }
} }

View File

@ -47,17 +47,6 @@ namespace Microsoft.Extensions.DependencyInjection
} }
} }
// dynamically register database providers
var databaseTypes = assembly.GetInterfaces<IOqtaneDatabase>();
foreach (var databaseType in databaseTypes)
{
if (databaseType.AssemblyQualifiedName != null)
{
var serviceType = Type.GetType("Oqtane.Interfaces.IOqtaneDatabase, Oqtane.Shared");
services.AddScoped(serviceType ?? databaseType, databaseType);
}
}
// dynamically register hosted services // dynamically register hosted services
var serviceTypes = assembly.GetTypes(hostedServiceType); var serviceTypes = assembly.GetTypes(hostedServiceType);
foreach (var serviceType in serviceTypes) foreach (var serviceType in serviceTypes)

View File

@ -30,6 +30,8 @@ namespace Oqtane.Infrastructure
private readonly IServiceScopeFactory _serviceScopeFactory; private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IMemoryCache _cache; private readonly IMemoryCache _cache;
private IOqtaneDatabase _database;
public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IMemoryCache cache) public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IMemoryCache cache)
{ {
_config = config; _config = config;
@ -185,18 +187,12 @@ namespace Oqtane.Infrastructure
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty); if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty);
var connectionString = NormalizeConnectionString(install.ConnectionString); var dbOptions = new DbContextOptionsBuilder().UseOqtaneDatabase(install.Database, NormalizeConnectionString(install.ConnectionString)).Options;
var databaseType = install.DatabaseType; using (var dbc = new DbContext(dbOptions))
using (var scope = _serviceScopeFactory.CreateScope())
{ {
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>(); // create empty database if it does not exist
dbc.Database.EnsureCreated();
using (var dbc = new DbContext(new DbContextOptionsBuilder().UseOqtaneDatabase(databases.Single(d => d.TypeName == databaseType), connectionString).Options)) result.Success = true;
{
// create empty database if it does not exist
dbc.Database.EnsureCreated();
result.Success = true;
}
} }
} }
catch (Exception ex) catch (Exception ex)
@ -220,16 +216,16 @@ namespace Oqtane.Infrastructure
{ {
using (var scope = _serviceScopeFactory.CreateScope()) using (var scope = _serviceScopeFactory.CreateScope())
{ {
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>(); var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
var installation = IsInstalled();
try try
{ {
var dbConfig = new DbConfig(null, null, databases) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType}; UpdateConnectionString(install.ConnectionString);
UpdateDatabaseType(install.DatabaseType);
using (var masterDbContext = new MasterDBContext(new DbContextOptions<MasterDBContext>(), dbConfig)) using (var masterDbContext = new MasterDBContext(new DbContextOptions<MasterDBContext>(), null, _config))
{ {
var installation = IsInstalled();
if (installation.Success && (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB")) if (installation.Success && (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB"))
{ {
UpgradeSqlServer(sql, install.ConnectionString, install.DatabaseType, true); UpgradeSqlServer(sql, install.ConnectionString, install.DatabaseType, true);
@ -244,10 +240,10 @@ namespace Oqtane.Infrastructure
result.Message = ex.Message; result.Message = ex.Message;
} }
if (result.Success) if (!result.Success)
{ {
UpdateConnectionString(install.ConnectionString); UpdateConnectionString(String.Empty);
UpdateDatabaseType(install.DatabaseType); UpdateDatabaseType(String.Empty);
} }
} }
} }
@ -265,11 +261,7 @@ namespace Oqtane.Infrastructure
if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases)) if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases))
{ {
using (var scope = _serviceScopeFactory.CreateScope()) using (var db = GetInstallationContext())
{
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
using (var db = GetInstallationContext(databases))
{ {
Tenant tenant; Tenant tenant;
if (install.IsNewTenant) if (install.IsNewTenant)
@ -315,7 +307,6 @@ namespace Oqtane.Infrastructure
_cache.Remove("aliases"); _cache.Remove("aliases");
} }
}
} }
result.Success = true; result.Success = true;
@ -332,19 +323,19 @@ namespace Oqtane.Infrastructure
using (var scope = _serviceScopeFactory.CreateScope()) using (var scope = _serviceScopeFactory.CreateScope())
{ {
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>(); var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>(); var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
using (var db = GetInstallationContext(databases)) using (var db = GetInstallationContext())
{ {
foreach (var tenant in db.Tenant.ToList()) foreach (var tenant in db.Tenant.ToList())
{ {
tenantManager.SetTenant(tenant.TenantId);
try try
{ {
var dbConfig = new DbConfig(null, null, databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; using (var tenantDbContext = new TenantDBContext(tenantManager, null))
using (var tenantDbContext = new TenantDBContext(dbConfig, null))
{ {
if (dbConfig.DatabaseType == "SqlServer" || dbConfig.DatabaseType == "LocalDB") if (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB")
{ {
UpgradeSqlServer(sql, tenant.DBConnectionString, tenant.DBType, false); UpgradeSqlServer(sql, tenant.DBConnectionString, tenant.DBType, false);
} }
@ -393,7 +384,6 @@ namespace Oqtane.Infrastructure
{ {
var moduleDefinitions = scope.ServiceProvider.GetRequiredService<IModuleDefinitionRepository>(); var moduleDefinitions = scope.ServiceProvider.GetRequiredService<IModuleDefinitionRepository>();
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>(); var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
foreach (var moduleDefinition in moduleDefinitions.GetModuleDefinitions()) foreach (var moduleDefinition in moduleDefinitions.GetModuleDefinitions())
{ {
@ -403,7 +393,7 @@ namespace Oqtane.Infrastructure
if (moduleType != null) if (moduleType != null)
{ {
var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
using (var db = GetInstallationContext(databases)) using (var db = GetInstallationContext())
{ {
foreach (var tenant in db.Tenant.ToList()) foreach (var tenant in db.Tenant.ToList())
{ {
@ -591,12 +581,19 @@ namespace Oqtane.Infrastructure
return connectionString; return connectionString;
} }
private InstallationContext GetInstallationContext(IEnumerable<IOqtaneDatabase> databases) private InstallationContext GetInstallationContext()
{ {
var connectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey);
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); IOqtaneDatabase database = null;
return new InstallationContext(databases.Single(d => d.TypeName == databaseType), connectionString); if (!String.IsNullOrEmpty(databaseType))
{
var type = Type.GetType(databaseType);
database = Activator.CreateInstance(type) as IOqtaneDatabase;
}
return new InstallationContext(database, connectionString);
} }
private string GetInstallationConfig(string key, string defaultValue) private string GetInstallationConfig(string key, string defaultValue)

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Master.01.00.00.00")] [Migration("Master.01.00.00.00")]
public class InitializeMaster : MultiDatabaseMigration public class InitializeMaster : MultiDatabaseMigration
{ {
public InitializeMaster(IEnumerable<IOqtaneDatabase> databases) : base(databases) public InitializeMaster(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -12,7 +12,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.01.00.00.00")] [Migration("Tenant.01.00.00.00")]
public class InitializeTenant : MultiDatabaseMigration public class InitializeTenant : MultiDatabaseMigration
{ {
public InitializeTenant(IEnumerable<IOqtaneDatabase> databases) : base(databases) public InitializeTenant(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Master.01.00.01.00")] [Migration("Master.01.00.01.00")]
public class AddAdditionalIndexesInMaster : MultiDatabaseMigration public class AddAdditionalIndexesInMaster : MultiDatabaseMigration
{ {
public AddAdditionalIndexesInMaster(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddAdditionalIndexesInMaster(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.01.00.01.00")] [Migration("Tenant.01.00.01.00")]
public class AddAdditionalIndexesInTenant : MultiDatabaseMigration public class AddAdditionalIndexesInTenant : MultiDatabaseMigration
{ {
public AddAdditionalIndexesInTenant(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddAdditionalIndexesInTenant(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.01.00.01.01")] [Migration("Tenant.01.00.01.01")]
public class AddAdditionColumnToNotifications : MultiDatabaseMigration public class AddAdditionColumnToNotifications : MultiDatabaseMigration
{ {
public AddAdditionColumnToNotifications(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddAdditionColumnToNotifications(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.01.00.02.01")] [Migration("Tenant.01.00.02.01")]
public class DropColumnFromPage : MultiDatabaseMigration public class DropColumnFromPage : MultiDatabaseMigration
{ {
public DropColumnFromPage(IEnumerable<IOqtaneDatabase> databases) : base(databases) public DropColumnFromPage(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.02.00.00.01")] [Migration("Tenant.02.00.00.01")]
public class AddColumnToProfileAndUpdatePage : MultiDatabaseMigration public class AddColumnToProfileAndUpdatePage : MultiDatabaseMigration
{ {
public AddColumnToProfileAndUpdatePage(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddColumnToProfileAndUpdatePage(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.02.00.01.01")] [Migration("Tenant.02.00.01.01")]
public class UpdateIconColumnInPage : MultiDatabaseMigration public class UpdateIconColumnInPage : MultiDatabaseMigration
{ {
public UpdateIconColumnInPage(IEnumerable<IOqtaneDatabase> databases) : base(databases) public UpdateIconColumnInPage(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.02.00.01.02")] [Migration("Tenant.02.00.01.02")]
public class AddLanguageTable : MultiDatabaseMigration public class AddLanguageTable : MultiDatabaseMigration
{ {
public AddLanguageTable(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddLanguageTable(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.02.00.01.03")] [Migration("Tenant.02.00.01.03")]
public class UpdatePageAndAddColumnToSite : MultiDatabaseMigration public class UpdatePageAndAddColumnToSite : MultiDatabaseMigration
{ {
public UpdatePageAndAddColumnToSite(IEnumerable<IOqtaneDatabase> databases) : base(databases) public UpdatePageAndAddColumnToSite(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -12,7 +12,7 @@ namespace Oqtane.Migrations
public class AddSiteGuidToSite : MultiDatabaseMigration public class AddSiteGuidToSite : MultiDatabaseMigration
{ {
public AddSiteGuidToSite(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddSiteGuidToSite(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.02.00.02.02")] [Migration("Tenant.02.00.02.02")]
public class UpdateDefaultContainerTypeInSitePage : MultiDatabaseMigration public class UpdateDefaultContainerTypeInSitePage : MultiDatabaseMigration
{ {
public UpdateDefaultContainerTypeInSitePage(IEnumerable<IOqtaneDatabase> databases) : base(databases) public UpdateDefaultContainerTypeInSitePage(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.02.00.02.03")] [Migration("Tenant.02.00.02.03")]
public class DropDefaultLayoutInSite : MultiDatabaseMigration public class DropDefaultLayoutInSite : MultiDatabaseMigration
{ {
public DropDefaultLayoutInSite(IEnumerable<IOqtaneDatabase> databases) : base(databases) public DropDefaultLayoutInSite(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -12,7 +12,7 @@ namespace Oqtane.Migrations
[Migration("Tenant.02.01.00.00")] [Migration("Tenant.02.01.00.00")]
public class AddAppVersionsTable : MultiDatabaseMigration public class AddAppVersionsTable : MultiDatabaseMigration
{ {
public AddAppVersionsTable(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddAppVersionsTable(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Master.02.01.00.00")] [Migration("Master.02.01.00.00")]
public class AddIndexesForForeignKeyInMaster : MultiDatabaseMigration public class AddIndexesForForeignKeyInMaster : MultiDatabaseMigration
{ {
public AddIndexesForForeignKeyInMaster(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddIndexesForForeignKeyInMaster(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -11,7 +11,7 @@ namespace Oqtane.Migrations
[Migration("Master.02.01.00.01")] [Migration("Master.02.01.00.01")]
public class AddDatabaseTypeColumnToTenant : MultiDatabaseMigration public class AddDatabaseTypeColumnToTenant : MultiDatabaseMigration
{ {
public AddDatabaseTypeColumnToTenant(IEnumerable<IOqtaneDatabase> databases) : base(databases) public AddDatabaseTypeColumnToTenant(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -7,14 +7,14 @@ namespace Oqtane.Migrations
{ {
public abstract class MultiDatabaseMigration : Migration public abstract class MultiDatabaseMigration : Migration
{ {
private readonly IEnumerable<IOqtaneDatabase> _databases; private readonly IOqtaneDatabase _databases;
protected MultiDatabaseMigration(IEnumerable<IOqtaneDatabase> databases) protected MultiDatabaseMigration(IOqtaneDatabase database)
{ {
_databases = databases; ActiveDatabase = database;
} }
protected IOqtaneDatabase ActiveDatabase => _databases.FirstOrDefault(d => d.Provider == ActiveProvider); protected IOqtaneDatabase ActiveDatabase { get; }
protected string RewriteName(string name) protected string RewriteName(string name)
{ {

View File

@ -13,7 +13,7 @@ namespace Oqtane.Migrations.Framework
{ {
public class MultiDatabaseMigrationsAssembly: MigrationsAssembly public class MultiDatabaseMigrationsAssembly: MigrationsAssembly
{ {
private readonly IEnumerable<IOqtaneDatabase> _databases; private readonly IOqtaneDatabase _database;
public MultiDatabaseMigrationsAssembly( public MultiDatabaseMigrationsAssembly(
ICurrentDbContext currentContext, ICurrentDbContext currentContext,
@ -23,15 +23,15 @@ namespace Oqtane.Migrations.Framework
: base(currentContext, options, idGenerator, logger) : base(currentContext, options, idGenerator, logger)
{ {
var multiDatabaseContext = currentContext.Context as IMultiDatabase; var multiDatabaseContext = currentContext.Context as IMultiDatabase;
if (multiDatabaseContext != null) _databases = multiDatabaseContext.Databases; if (multiDatabaseContext != null) _database = multiDatabaseContext.ActiveDatabase;
} }
public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider) public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider)
{ {
var hasCtorWithCacheOptions = migrationClass.GetConstructor(new[] { typeof(IEnumerable<IOqtaneDatabase>) }) != null; var hasCtorWithCacheOptions = migrationClass.GetConstructor(new[] { typeof(IOqtaneDatabase) }) != null;
if (hasCtorWithCacheOptions) if (hasCtorWithCacheOptions)
{ {
var migration = (Migration)Activator.CreateInstance(migrationClass.AsType(), _databases); var migration = (Migration)Activator.CreateInstance(migrationClass.AsType(), _database);
if (migration != null) if (migration != null)
{ {
migration.ActiveProvider = activeProvider; migration.ActiveProvider = activeProvider;

View File

@ -6,6 +6,7 @@ using Oqtane.Repository;
using Oqtane.Modules.HtmlText.Models; using Oqtane.Modules.HtmlText.Models;
using Oqtane.Modules.HtmlText.Repository; using Oqtane.Modules.HtmlText.Repository;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Enums; using Oqtane.Enums;
@ -18,12 +19,15 @@ namespace Oqtane.Modules.HtmlText.Manager
public class HtmlTextManager : MigratableModuleBase, IInstallable, IPortable public class HtmlTextManager : MigratableModuleBase, IInstallable, IPortable
{ {
private readonly IHtmlTextRepository _htmlText; private readonly IHtmlTextRepository _htmlText;
private readonly IEnumerable<IOqtaneDatabase> _databases; private readonly ITenantManager _tenantManager;
private readonly IHttpContextAccessor _accessor;
public HtmlTextManager(IHtmlTextRepository htmlText, IEnumerable<IOqtaneDatabase> databases)
public HtmlTextManager(IHtmlTextRepository htmlText, ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor)
{ {
_htmlText = htmlText; _htmlText = htmlText;
_databases = databases; _tenantManager = tenantManager;
_accessor = httpContextAccessor;
} }
public string ExportModule(Module module) public string ExportModule(Module module)
@ -57,14 +61,12 @@ namespace Oqtane.Modules.HtmlText.Manager
public bool Install(Tenant tenant, string version) public bool Install(Tenant tenant, string version)
{ {
var dbConfig = new DbConfig(null, null, _databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; return Migrate(new HtmlTextContext(_tenantManager, _accessor), tenant, MigrationType.Up);
return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Up);
} }
public bool Uninstall(Tenant tenant) public bool Uninstall(Tenant tenant)
{ {
var dbConfig = new DbConfig(null, null, _databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; return Migrate(new HtmlTextContext(_tenantManager, _accessor), tenant, MigrationType.Down);
return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Down);
} }
} }
} }

View File

@ -12,7 +12,7 @@ namespace Oqtane.Modules.HtmlText.Migrations
[Migration("HtmlText.01.00.00.00")] [Migration("HtmlText.01.00.00.00")]
public class InitializeModule : MultiDatabaseMigration public class InitializeModule : MultiDatabaseMigration
{ {
public InitializeModule(IEnumerable<IOqtaneDatabase> databases) : base(databases) public InitializeModule(IOqtaneDatabase database) : base(database)
{ {
} }

View File

@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Repository; using Oqtane.Repository;
@ -10,9 +11,7 @@ namespace Oqtane.Modules.HtmlText.Repository
{ {
public class HtmlTextContext : DBContextBase, IService, IMultiDatabase public class HtmlTextContext : DBContextBase, IService, IMultiDatabase
{ {
public HtmlTextContext(IDbConfig dbConfig, ITenantManager tenantManager) : base(dbConfig, tenantManager) public HtmlTextContext(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor) : base(tenantManager, httpContextAccessor) { }
{
}
public virtual DbSet<Models.HtmlText> HtmlText { get; set; } public virtual DbSet<Models.HtmlText> HtmlText { get; set; }
} }

View File

@ -23,7 +23,6 @@ namespace Oqtane.Repository
private readonly ITenantResolver _tenantResolver; private readonly ITenantResolver _tenantResolver;
private readonly ITenantManager _tenantManager; private readonly ITenantManager _tenantManager;
private readonly IHttpContextAccessor _accessor; private readonly IHttpContextAccessor _accessor;
private readonly IConfiguration _configuration;
private string _connectionString; private string _connectionString;
private string _databaseType; private string _databaseType;
@ -34,17 +33,7 @@ namespace Oqtane.Repository
_accessor = httpContextAccessor; _accessor = httpContextAccessor;
} }
public DBContextBase(IDbConfig dbConfig, ITenantManager tenantManager) public IOqtaneDatabase ActiveDatabase { get; private set; }
{
_accessor = dbConfig.Accessor;
_configuration = dbConfig.Configuration;
_connectionString = dbConfig.ConnectionString;
_databaseType = dbConfig.DatabaseType;
Databases = dbConfig.Databases;
_tenantManager = tenantManager;
}
public IEnumerable<IOqtaneDatabase> Databases { get; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{ {
@ -69,27 +58,17 @@ namespace Oqtane.Repository
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
_databaseType = tenant.DBType; _databaseType = tenant.DBType;
} }
else
{
if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
{
_connectionString = _configuration.GetConnectionString("DefaultConnection")
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
}
_databaseType = _configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
}
} }
if (!string.IsNullOrEmpty(_connectionString) && !string.IsNullOrEmpty(_databaseType)) if (!String.IsNullOrEmpty(_databaseType))
{ {
if (Databases != null) var type = Type.GetType(_databaseType);
{ ActiveDatabase = Activator.CreateInstance(type) as IOqtaneDatabase;
optionsBuilder.UseOqtaneDatabase(Databases.Single(d => d.TypeName == _databaseType), _connectionString); }
}
else if (!string.IsNullOrEmpty(_connectionString) && ActiveDatabase != null)
{ {
optionsBuilder.UseOqtaneDatabase(_databaseType, _connectionString); optionsBuilder.UseOqtaneDatabase(ActiveDatabase, _connectionString);
}
} }
base.OnConfiguring(optionsBuilder); base.OnConfiguring(optionsBuilder);
@ -99,13 +78,7 @@ namespace Oqtane.Repository
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
if (Databases != null) ActiveDatabase.UpdateIdentityStoreTableNames(builder);
{
var database = Databases.Single(d => d.TypeName == _databaseType);
database.UpdateIdentityStoreTableNames(builder);
}
} }
public override int SaveChanges() public override int SaveChanges()
@ -122,17 +95,5 @@ namespace Oqtane.Repository
_tenantResolver = tenantResolver; _tenantResolver = tenantResolver;
_accessor = httpContextAccessor; _accessor = httpContextAccessor;
} }
[Obsolete("This constructor is obsolete. Use DBContextBase(IDbConfig dbConfig, ITenantManager tenantManager) instead.", false)]
public DBContextBase(IDbConfig dbConfig, ITenantResolver tenantResolver)
{
_accessor = dbConfig.Accessor;
_configuration = dbConfig.Configuration;
_connectionString = dbConfig.ConnectionString;
_databaseType = dbConfig.DatabaseType;
Databases = dbConfig.Databases;
_tenantResolver = tenantResolver;
}
} }
} }

View File

@ -1,27 +0,0 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Oqtane.Interfaces;
namespace Oqtane.Repository
{
public class DbConfig : IDbConfig
{
public DbConfig(IHttpContextAccessor accessor, IConfiguration configuration, IEnumerable<IOqtaneDatabase> databases)
{
Accessor = accessor;
Configuration = configuration;
Databases = databases;
}
public IHttpContextAccessor Accessor { get; }
public IConfiguration Configuration { get; }
public IEnumerable<IOqtaneDatabase> Databases { get; set; }
public string ConnectionString { get; set; }
public string DatabaseType { get; set; }
}
}

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Models; using Oqtane.Models;
@ -19,45 +20,43 @@ namespace Oqtane.Repository
{ {
public class MasterDBContext : DbContext, IMultiDatabase public class MasterDBContext : DbContext, IMultiDatabase
{ {
private readonly IDbConfig _dbConfig; private readonly IHttpContextAccessor _accessor;
private readonly IConfiguration _configuration;
private string _connectionString;
private string _databaseType;
public MasterDBContext(DbContextOptions<MasterDBContext> options, IDbConfig dbConfig) : base(options) public MasterDBContext(DbContextOptions<MasterDBContext> options, IHttpContextAccessor accessor, IConfiguration configuration) : base(options)
{ {
_dbConfig = dbConfig; _accessor = accessor;
Databases = dbConfig.Databases; _configuration = configuration;
} }
public IEnumerable<IOqtaneDatabase> Databases { get; } public IOqtaneDatabase ActiveDatabase { get; private set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{ {
optionsBuilder.ReplaceService<IMigrationsAssembly, MultiDatabaseMigrationsAssembly>(); optionsBuilder.ReplaceService<IMigrationsAssembly, MultiDatabaseMigrationsAssembly>();
var connectionString = _dbConfig.ConnectionString; if(_configuration != null)
var configuration = _dbConfig.Configuration;
var databaseType = _dbConfig.DatabaseType;
if(string.IsNullOrEmpty(connectionString) && configuration != null)
{ {
if (!String.IsNullOrEmpty(configuration.GetConnectionString("DefaultConnection"))) if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
{ {
connectionString = configuration.GetConnectionString("DefaultConnection") _connectionString = _configuration.GetConnectionString("DefaultConnection")
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
} }
databaseType = configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; _databaseType = _configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
} }
if (!string.IsNullOrEmpty(connectionString) && !string.IsNullOrEmpty(databaseType)) if (!String.IsNullOrEmpty(_databaseType))
{ {
if (Databases != null) var type = Type.GetType(_databaseType);
{ ActiveDatabase = Activator.CreateInstance(type) as IOqtaneDatabase;
optionsBuilder.UseOqtaneDatabase(Databases.Single(d => d.TypeName == databaseType), connectionString); }
}
else if (!string.IsNullOrEmpty(_connectionString) && ActiveDatabase != null)
{ {
optionsBuilder.UseOqtaneDatabase(databaseType, connectionString); optionsBuilder.UseOqtaneDatabase(ActiveDatabase, _connectionString);
}
} }
base.OnConfiguring(optionsBuilder); base.OnConfiguring(optionsBuilder);
@ -71,7 +70,7 @@ namespace Oqtane.Repository
public override int SaveChanges() public override int SaveChanges()
{ {
DbContextUtils.SaveChanges(this, _dbConfig.Accessor); DbContextUtils.SaveChanges(this, _accessor);
return base.SaveChanges(); return base.SaveChanges();
} }

View File

@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Models; using Oqtane.Models;
@ -11,7 +12,7 @@ namespace Oqtane.Repository
{ {
public class TenantDBContext : DBContextBase, IMultiDatabase public class TenantDBContext : DBContextBase, IMultiDatabase
{ {
public TenantDBContext(IDbConfig dbConfig, ITenantManager tenantManager) : base(dbConfig, tenantManager) { } public TenantDBContext(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor) : base(tenantManager, httpContextAccessor) { }
public virtual DbSet<Site> Site { get; set; } public virtual DbSet<Site> Site { get; set; }
public virtual DbSet<Page> Page { get; set; } public virtual DbSet<Page> Page { get; set; }

View File

@ -1,20 +0,0 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Oqtane.Interfaces;
namespace Oqtane.Repository
{
public interface IDbConfig
{
public IHttpContextAccessor Accessor { get; }
public IConfiguration Configuration { get; }
public IEnumerable<IOqtaneDatabase> Databases { get; set; }
public string ConnectionString { get; set; }
public string DatabaseType { get; set; }
}
}

View File

@ -14,13 +14,6 @@ namespace Oqtane.Repository
{ {
public class SqlRepository : ISqlRepository public class SqlRepository : ISqlRepository
{ {
private IEnumerable<IOqtaneDatabase> _databases;
public SqlRepository(IEnumerable<IOqtaneDatabase> databases)
{
_databases = databases;
}
public void ExecuteScript(Tenant tenant, string script) public void ExecuteScript(Tenant tenant, string script)
{ {
// execute script in current tenant // execute script in current tenant
@ -80,14 +73,13 @@ namespace Oqtane.Repository
public IDataReader ExecuteReader(Tenant tenant, string query) public IDataReader ExecuteReader(Tenant tenant, string query)
{ {
var db = _databases.Single(d => d.TypeName == tenant.DBType); var db = GetActiveDatabase(tenant.DBType);
return db.ExecuteReader(tenant.DBConnectionString, query); return db.ExecuteReader(tenant.DBConnectionString, query);
} }
private int ExecuteNonQuery(string connectionString, string databaseType, string query) private int ExecuteNonQuery(string connectionString, string databaseType, string query)
{ {
var db = _databases.Single(d => d.TypeName == databaseType); var db = GetActiveDatabase(databaseType);
return db.ExecuteNonQuery(connectionString, query); return db.ExecuteNonQuery(connectionString, query);
} }
@ -114,5 +106,17 @@ namespace Oqtane.Repository
return script; return script;
} }
private IOqtaneDatabase GetActiveDatabase(string databaseType)
{
IOqtaneDatabase activeDatabase = null;
if (!String.IsNullOrEmpty(databaseType))
{
var type = Type.GetType(databaseType);
activeDatabase = Activator.CreateInstance(type) as IOqtaneDatabase;
}
return activeDatabase;
}
} }
} }

View File

@ -210,7 +210,6 @@ namespace Oqtane
// load the external assemblies into the app domain, install services // load the external assemblies into the app domain, install services
services.AddOqtane(_runtime, _supportedCultures); services.AddOqtane(_runtime, _supportedCultures);
services.AddScoped<IDbConfig, DbConfig>();
services.AddDbContext<MasterDBContext>(options => { }); services.AddDbContext<MasterDBContext>(options => { });
services.AddDbContext<TenantDBContext>(options => { }); services.AddDbContext<TenantDBContext>(options => { });

View File

@ -1,9 +1,29 @@
using System;
using Oqtane.Interfaces;
namespace Oqtane.Shared namespace Oqtane.Shared
{ {
public class InstallConfig public class InstallConfig
{ {
private IOqtaneDatabase _database;
public string ConnectionString { get; set; } public string ConnectionString { get; set; }
public string DatabaseType { get; set; } public string DatabaseType { get; set; }
public IOqtaneDatabase Database
{
get
{
if (_database == null)
{
var type = Type.GetType(DatabaseType);
_database = Activator.CreateInstance(type) as IOqtaneDatabase;
}
return _database;
}
}
public string Aliases { get; set; } public string Aliases { get; set; }
public string TenantName { get; set; } public string TenantName { get; set; }
public bool IsNewTenant { get; set; } public bool IsNewTenant { get; set; }