fix #2567 - migrate tenant connection string details from database to appsettings.json
This commit is contained in:
@ -52,7 +52,7 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
var installation = new Installation { Success = false, Message = "" };
|
||||
|
||||
if (ModelState.IsValid && (User.IsInRole(RoleNames.Host) || string.IsNullOrEmpty(_configManager.GetSetting("ConnectionStrings:" + SettingKeys.ConnectionStringKey, ""))))
|
||||
if (ModelState.IsValid && (User.IsInRole(RoleNames.Host) || string.IsNullOrEmpty(_configManager.GetSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", ""))))
|
||||
{
|
||||
installation = _databaseManager.Install(config);
|
||||
|
||||
|
@ -32,13 +32,23 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
var results = new List<Dictionary<string, string>>();
|
||||
Dictionary<string, string> row;
|
||||
Tenant tenant = _tenants.GetTenant(sqlquery.TenantId);
|
||||
|
||||
if (string.IsNullOrEmpty(sqlquery.DBType) || string.IsNullOrEmpty(sqlquery.DBConnectionString))
|
||||
{
|
||||
Tenant tenant = _tenants.GetTenant(sqlquery.TenantId);
|
||||
if (tenant != null)
|
||||
{
|
||||
sqlquery.DBType = tenant.DBType;
|
||||
sqlquery.DBConnectionString = tenant.DBConnectionString;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (string query in sqlquery.Query.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
IDataReader dr = _sql.ExecuteReader(tenant, query);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Other, "Sql Query {Query} Executed on Tenant {TenantId}", query, sqlquery.TenantId);
|
||||
IDataReader dr = _sql.ExecuteReader(sqlquery.DBType, sqlquery.DBConnectionString, query);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Other, "Sql Query {Query} Executed on Database {DBType} and Connection {DBConnectionString}", query, sqlquery.DBType, sqlquery.DBConnectionString);
|
||||
while (dr.Read())
|
||||
{
|
||||
row = new Dictionary<string, string>();
|
||||
@ -53,7 +63,7 @@ namespace Oqtane.Controllers
|
||||
catch (Exception ex)
|
||||
{
|
||||
results.Add(new Dictionary<string, string>() { { "Error", ex.Message } });
|
||||
_logger.Log(LogLevel.Warning, this, LogFunction.Other, "Sql Query {Query} Executed on Tenant {TenantId} Resulted In An Error {Error}", sqlquery.Query, sqlquery.TenantId, ex.Message);
|
||||
_logger.Log(LogLevel.Warning, this, LogFunction.Other, "Sql Query {Query} Executed on Database {DBType} and Connection {DBConnectionString} Resulted In An Error {Error}", sqlquery.Query, sqlquery.DBType, sqlquery.DBConnectionString, ex.Message);
|
||||
}
|
||||
sqlquery.Results = results;
|
||||
return sqlquery;
|
||||
|
@ -63,6 +63,12 @@ namespace Oqtane.Controllers
|
||||
}
|
||||
systeminfo.Add("Log", log);
|
||||
break;
|
||||
case "connectionstrings":
|
||||
foreach (var kvp in _configManager.GetSettings(SettingKeys.ConnectionStringsSection))
|
||||
{
|
||||
systeminfo.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return systeminfo;
|
||||
@ -88,19 +94,11 @@ namespace Oqtane.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
// PUT: api/<controller>
|
||||
[HttpPut("{key}/{value}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public void Put(string key, object value)
|
||||
{
|
||||
UpdateSetting(key, value);
|
||||
}
|
||||
|
||||
private void UpdateSetting(string key, object value)
|
||||
{
|
||||
switch (key)
|
||||
switch (key.ToLower())
|
||||
{
|
||||
case "Log":
|
||||
case "clearlog":
|
||||
string path = Path.Combine(_environment.ContentRootPath, "Content", "Log", "error.log");
|
||||
if (System.IO.File.Exists(path))
|
||||
{
|
||||
|
@ -72,6 +72,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
|
||||
internal static IServiceCollection AddOqtaneTransientServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<IDBContextDependencies, DBContextDependencies>();
|
||||
services.AddTransient<ITenantManager, TenantManager>();
|
||||
services.AddTransient<IAliasAccessor, AliasAccessor>();
|
||||
services.AddTransient<IUserPermissions, UserPermissions>();
|
||||
|
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -42,6 +44,16 @@ namespace Oqtane.Infrastructure
|
||||
return value;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetSettings(string sectionKey)
|
||||
{
|
||||
var settings = new Dictionary<string, string>();
|
||||
foreach (var kvp in _config.GetSection(sectionKey).GetChildren().AsEnumerable())
|
||||
{
|
||||
settings.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
public void AddOrUpdateSetting<T>(string key, T value, bool reload)
|
||||
{
|
||||
AddOrUpdateSetting("appsettings.json", key, value, reload);
|
||||
|
@ -162,6 +162,16 @@ namespace Oqtane.Infrastructure
|
||||
{
|
||||
install.DefaultContainer = GetInstallationConfig(SettingKeys.DefaultContainerKey, Constants.DefaultContainer);
|
||||
}
|
||||
|
||||
// add new site
|
||||
if (install.TenantName != TenantNames.Master && install.ConnectionString.Contains("="))
|
||||
{
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.ConnectionStringsSection}:{install.TenantName}", install.ConnectionString, false);
|
||||
}
|
||||
if (install.TenantName == TenantNames.Master && !install.ConnectionString.Contains("="))
|
||||
{
|
||||
install.ConnectionString = _config.GetConnectionString(install.ConnectionString);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -273,7 +283,7 @@ namespace Oqtane.Infrastructure
|
||||
var database = Activator.CreateInstance(type) as IDatabase;
|
||||
|
||||
// create data directory if does not exist
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString();
|
||||
if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty);
|
||||
|
||||
var dbOptions = new DbContextOptionsBuilder().UseOqtaneDatabase(database, NormalizeConnectionString(install.ConnectionString)).Options;
|
||||
@ -316,10 +326,7 @@ namespace Oqtane.Infrastructure
|
||||
|
||||
using (var masterDbContext = new MasterDBContext(new DbContextOptions<MasterDBContext>(), null, _config))
|
||||
{
|
||||
if (installation.Success && (install.DatabaseType == Constants.DefaultDBType))
|
||||
{
|
||||
UpgradeSqlServer(sql, install.ConnectionString, install.DatabaseType, true);
|
||||
}
|
||||
AddEFMigrationsHistory(sql, install.ConnectionString, install.DatabaseType, "", true);
|
||||
// push latest model into database
|
||||
masterDbContext.Database.Migrate();
|
||||
result.Success = true;
|
||||
@ -354,7 +361,7 @@ namespace Oqtane.Infrastructure
|
||||
tenant = new Tenant
|
||||
{
|
||||
Name = install.TenantName,
|
||||
DBConnectionString = DenormalizeConnectionString(install.ConnectionString),
|
||||
DBConnectionString = (install.TenantName == TenantNames.Master) ? SettingKeys.ConnectionStringKey : install.TenantName,
|
||||
DBType = install.DatabaseType,
|
||||
CreatedBy = "",
|
||||
CreatedOn = DateTime.UtcNow,
|
||||
@ -413,21 +420,19 @@ namespace Oqtane.Infrastructure
|
||||
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
|
||||
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||
var DBContextDependencies = scope.ServiceProvider.GetRequiredService<IDBContextDependencies>();
|
||||
|
||||
using (var db = GetInstallationContext())
|
||||
{
|
||||
foreach (var tenant in db.Tenant.ToList())
|
||||
{
|
||||
tenantManager.SetTenant(tenant.TenantId);
|
||||
tenant.DBConnectionString = MigrateConnectionString(db, tenant);
|
||||
try
|
||||
{
|
||||
using (var tenantDbContext = new TenantDBContext(tenantManager, null))
|
||||
using (var tenantDbContext = new TenantDBContext(DBContextDependencies))
|
||||
{
|
||||
if (install.DatabaseType == Constants.DefaultDBType)
|
||||
{
|
||||
UpgradeSqlServer(sql, tenant.DBConnectionString, tenant.DBType, false);
|
||||
}
|
||||
|
||||
AddEFMigrationsHistory(sql, _configManager.GetSetting($"{SettingKeys.ConnectionStringsSection}:{tenant.DBConnectionString}", ""), tenant.DBType, tenant.Version, false);
|
||||
// push latest model into database
|
||||
tenantDbContext.Database.Migrate();
|
||||
result.Success = true;
|
||||
@ -753,8 +758,8 @@ namespace Oqtane.Infrastructure
|
||||
|
||||
private string DenormalizeConnectionString(string connectionString)
|
||||
{
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||
connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|");
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString();
|
||||
connectionString = connectionString.Replace(dataDirectory ?? String.Empty, $"|{Constants.DataDirectory}|");
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
@ -780,8 +785,8 @@ namespace Oqtane.Infrastructure
|
||||
|
||||
private string NormalizeConnectionString(string connectionString)
|
||||
{
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||
connectionString = connectionString.Replace("|DataDirectory|", dataDirectory);
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString();
|
||||
connectionString = connectionString.Replace($"|{Constants.DataDirectory}|", dataDirectory);
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
@ -799,14 +804,39 @@ namespace Oqtane.Infrastructure
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType, true);
|
||||
}
|
||||
|
||||
public void UpgradeSqlServer(ISqlRepository sql, string connectionString, string databaseType, bool isMaster)
|
||||
public void AddEFMigrationsHistory(ISqlRepository sql, string connectionString, string databaseType, string version, bool isMaster)
|
||||
{
|
||||
var script = (isMaster) ? "MigrateMaster.sql" : "MigrateTenant.sql";
|
||||
// in version 2.1.0 the __EFMigrationsHistory tables were introduced and must be added to existing SQL Server installations
|
||||
if ((isMaster || (version != null && Version.Parse(version).CompareTo(Version.Parse("2.1.0")) < 0)) && databaseType == Constants.DefaultDBType)
|
||||
{
|
||||
var script = (isMaster) ? "MigrateMaster.sql" : "MigrateTenant.sql";
|
||||
|
||||
var query = sql.GetScriptFromAssembly(Assembly.GetExecutingAssembly(), script);
|
||||
query = query.Replace("{{Version}}", Constants.Version);
|
||||
var query = sql.GetScriptFromAssembly(Assembly.GetExecutingAssembly(), script);
|
||||
query = query.Replace("{{Version}}", Constants.Version);
|
||||
|
||||
sql.ExecuteNonQuery(connectionString, databaseType, query);
|
||||
sql.ExecuteNonQuery(connectionString, databaseType, query);
|
||||
}
|
||||
}
|
||||
|
||||
public string MigrateConnectionString(InstallationContext db, Tenant tenant)
|
||||
{
|
||||
// migrate connection strings from the Tenant table to appsettings
|
||||
if (tenant.DBConnectionString.Contains("="))
|
||||
{
|
||||
var defaultConnection = _configManager.GetConnectionString(SettingKeys.ConnectionStringKey);
|
||||
if (tenant.DBConnectionString == defaultConnection)
|
||||
{
|
||||
tenant.DBConnectionString = SettingKeys.ConnectionStringKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.ConnectionStringsSection}:{tenant.Name}", tenant.DBConnectionString, false);
|
||||
tenant.DBConnectionString = tenant.Name;
|
||||
}
|
||||
db.Entry(tenant).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
}
|
||||
return tenant.DBConnectionString;
|
||||
}
|
||||
|
||||
private void ValidateConfiguration()
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
@ -7,6 +8,7 @@ namespace Oqtane.Infrastructure
|
||||
public IConfigurationSection GetSection(string sectionKey);
|
||||
public T GetSetting<T>(string settingKey, T defaultValue);
|
||||
public T GetSetting<T>(string sectionKey, string settingKey, T defaultValue);
|
||||
public Dictionary<string, string> GetSettings(string sectionKey);
|
||||
void AddOrUpdateSetting<T>(string key, T value, bool reload);
|
||||
void AddOrUpdateSetting<T>(string file, string key, T value, bool reload);
|
||||
void RemoveSetting(string key, bool reload);
|
||||
|
@ -2,7 +2,6 @@ using Oqtane.Infrastructure;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Modules.HtmlText.Repository;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Shared;
|
||||
@ -17,15 +16,13 @@ namespace Oqtane.Modules.HtmlText.Manager
|
||||
public class HtmlTextManager : MigratableModuleBase, IInstallable, IPortable
|
||||
{
|
||||
private readonly IHtmlTextRepository _htmlText;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly IDBContextDependencies _DBContextDependencies;
|
||||
private readonly ISqlRepository _sqlRepository;
|
||||
|
||||
public HtmlTextManager(IHtmlTextRepository htmlText, ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor, ISqlRepository sqlRepository)
|
||||
public HtmlTextManager(IHtmlTextRepository htmlText, IDBContextDependencies DBContextDependencies, ISqlRepository sqlRepository)
|
||||
{
|
||||
_htmlText = htmlText;
|
||||
_tenantManager = tenantManager;
|
||||
_accessor = httpContextAccessor;
|
||||
_DBContextDependencies = DBContextDependencies;
|
||||
_sqlRepository = sqlRepository;
|
||||
}
|
||||
|
||||
@ -56,12 +53,12 @@ namespace Oqtane.Modules.HtmlText.Manager
|
||||
// version 1.0.0 used SQL scripts rather than migrations, so we need to seed the migration history table
|
||||
_sqlRepository.ExecuteNonQuery(tenant, MigrationUtils.BuildInsertScript("HtmlText.01.00.00.00"));
|
||||
}
|
||||
return Migrate(new HtmlTextContext(_tenantManager, _accessor), tenant, MigrationType.Up);
|
||||
return Migrate(new HtmlTextContext(_DBContextDependencies), tenant, MigrationType.Up);
|
||||
}
|
||||
|
||||
public bool Uninstall(Tenant tenant)
|
||||
{
|
||||
return Migrate(new HtmlTextContext(_tenantManager, _accessor), tenant, MigrationType.Down);
|
||||
return Migrate(new HtmlTextContext(_DBContextDependencies), tenant, MigrationType.Down);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace Oqtane.Modules.HtmlText.Repository
|
||||
[PrivateApi("Mark HtmlText classes as private, since it's not very useful in the public docs")]
|
||||
public class HtmlTextContext : DBContextBase, ITransientService, IMultiDatabase
|
||||
{
|
||||
public HtmlTextContext(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor) : base(tenantManager, httpContextAccessor) { }
|
||||
public HtmlTextContext(IDBContextDependencies DBContextDependencies) : base(DBContextDependencies) { }
|
||||
|
||||
public virtual DbSet<Models.HtmlText> HtmlText { get; set; }
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@ -6,11 +7,13 @@ using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Extensions;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Migrations.Framework;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
|
||||
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||
|
||||
@ -18,17 +21,17 @@ namespace Oqtane.Repository
|
||||
{
|
||||
public class DBContextBase : IdentityUserContext<IdentityUser>
|
||||
{
|
||||
private readonly ITenantResolver _tenantResolver;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private string _connectionString;
|
||||
private string _databaseType;
|
||||
private readonly IConfigurationRoot _config;
|
||||
private string _connectionString = "";
|
||||
private string _databaseType = "";
|
||||
|
||||
public DBContextBase(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor)
|
||||
public DBContextBase(IDBContextDependencies DBContextDependencies)
|
||||
{
|
||||
_connectionString = String.Empty;
|
||||
_tenantManager = tenantManager;
|
||||
_accessor = httpContextAccessor;
|
||||
_tenantManager = DBContextDependencies.TenantManager;
|
||||
_accessor = DBContextDependencies.Accessor;
|
||||
_config = DBContextDependencies.Config;
|
||||
}
|
||||
|
||||
public IDatabase ActiveDatabase { get; set; }
|
||||
@ -39,21 +42,11 @@ namespace Oqtane.Repository
|
||||
|
||||
if (string.IsNullOrEmpty(_connectionString))
|
||||
{
|
||||
|
||||
Tenant tenant;
|
||||
if (_tenantResolver != null)
|
||||
{
|
||||
tenant = _tenantResolver.GetTenant();
|
||||
}
|
||||
else
|
||||
{
|
||||
tenant = _tenantManager.GetTenant();
|
||||
}
|
||||
|
||||
Tenant tenant = _tenantManager.GetTenant();
|
||||
if (tenant != null)
|
||||
{
|
||||
_connectionString = tenant.DBConnectionString
|
||||
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
|
||||
_connectionString = _config.GetConnectionString(tenant.DBConnectionString)
|
||||
.Replace($"|{Constants.DataDirectory}|", AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString());
|
||||
_databaseType = tenant.DBType;
|
||||
}
|
||||
}
|
||||
@ -93,12 +86,17 @@ namespace Oqtane.Repository
|
||||
return base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
[Obsolete("This constructor is obsolete. Use DBContextBase(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor) instead.", false)]
|
||||
public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor httpContextAccessor)
|
||||
[Obsolete("This constructor is obsolete. Use DBContextBase(IDBContextDependencies DBContextDependencies) instead.", false)]
|
||||
public DBContextBase(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_connectionString = String.Empty;
|
||||
_tenantResolver = tenantResolver;
|
||||
_tenantManager = tenantManager;
|
||||
_accessor = httpContextAccessor;
|
||||
|
||||
// anti-pattern used to reference config service in base class without causing breaking change
|
||||
_config = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
20
Oqtane.Server/Repository/Context/DBContextDependencies.cs
Normal file
20
Oqtane.Server/Repository/Context/DBContextDependencies.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Oqtane.Infrastructure;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public class DBContextDependencies : IDBContextDependencies
|
||||
{
|
||||
public DBContextDependencies(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor, IConfigurationRoot config)
|
||||
{
|
||||
TenantManager = tenantManager;
|
||||
Accessor = httpContextAccessor;
|
||||
Config = config;
|
||||
}
|
||||
|
||||
public ITenantManager TenantManager { get; }
|
||||
public IHttpContextAccessor Accessor { get; }
|
||||
public IConfigurationRoot Config { get; }
|
||||
}
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Extensions;
|
||||
using Oqtane.Interfaces;
|
||||
using Oqtane.Models;
|
||||
using IDatabase = Oqtane.Databases.Interfaces.IDatabase;
|
||||
|
||||
|
@ -41,8 +41,8 @@ namespace Oqtane.Repository
|
||||
{
|
||||
if (_config.IsInstalled())
|
||||
{
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection")
|
||||
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
|
||||
_connectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey)
|
||||
.Replace($"|{Constants.DataDirectory}|", AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString());
|
||||
}
|
||||
|
||||
_databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
||||
|
@ -1,6 +1,4 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Repository.Databases.Interfaces;
|
||||
|
||||
@ -12,7 +10,7 @@ namespace Oqtane.Repository
|
||||
{
|
||||
public class TenantDBContext : DBContextBase, IMultiDatabase
|
||||
{
|
||||
public TenantDBContext(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor) : base(tenantManager, httpContextAccessor) { }
|
||||
public TenantDBContext(IDBContextDependencies DBContextDependencies) : base(DBContextDependencies) { }
|
||||
|
||||
public virtual DbSet<Site> Site { get; set; }
|
||||
public virtual DbSet<Page> Page { get; set; }
|
||||
|
@ -0,0 +1,13 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Oqtane.Infrastructure;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface IDBContextDependencies
|
||||
{
|
||||
ITenantManager TenantManager { get; }
|
||||
IHttpContextAccessor Accessor { get; }
|
||||
IConfigurationRoot Config { get; }
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System.Data;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using Oqtane.Models;
|
||||
|
||||
@ -18,6 +18,8 @@ namespace Oqtane.Repository
|
||||
|
||||
IDataReader ExecuteReader(Tenant tenant, string query);
|
||||
|
||||
IDataReader ExecuteReader(string DBType, string DBConnectionString, string query);
|
||||
|
||||
string GetScriptFromAssembly(Assembly assembly, string fileName);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Interfaces;
|
||||
using Oqtane.Models;
|
||||
// ReSharper disable ConvertToUsingDeclaration
|
||||
// ReSharper disable InvertIf
|
||||
@ -15,6 +14,13 @@ namespace Oqtane.Repository
|
||||
{
|
||||
public class SqlRepository : ISqlRepository
|
||||
{
|
||||
private IConfigurationRoot _config;
|
||||
|
||||
public SqlRepository(IConfigurationRoot config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public void ExecuteScript(Tenant tenant, string script)
|
||||
{
|
||||
// execute script in current tenant
|
||||
@ -75,13 +81,19 @@ namespace Oqtane.Repository
|
||||
public IDataReader ExecuteReader(Tenant tenant, string query)
|
||||
{
|
||||
var db = GetActiveDatabase(tenant.DBType);
|
||||
return db.ExecuteReader(tenant.DBConnectionString, query);
|
||||
return db.ExecuteReader(GetConnectionString(tenant.DBConnectionString), query);
|
||||
}
|
||||
|
||||
public IDataReader ExecuteReader(string DBType, string DBConnectionString, string query)
|
||||
{
|
||||
var db = GetActiveDatabase(DBType);
|
||||
return db.ExecuteReader(GetConnectionString(DBConnectionString), query);
|
||||
}
|
||||
|
||||
public int ExecuteNonQuery(string connectionString, string databaseType, string query)
|
||||
{
|
||||
var db = GetActiveDatabase(databaseType);
|
||||
return db.ExecuteNonQuery(connectionString, query);
|
||||
return db.ExecuteNonQuery(GetConnectionString(connectionString), query);
|
||||
}
|
||||
|
||||
public string GetScriptFromAssembly(Assembly assembly, string fileName)
|
||||
@ -119,5 +131,14 @@ namespace Oqtane.Repository
|
||||
|
||||
return activeDatabase;
|
||||
}
|
||||
|
||||
private string GetConnectionString(string connectionString)
|
||||
{
|
||||
if (!connectionString.Contains("="))
|
||||
{
|
||||
connectionString = _config.GetConnectionString(connectionString);
|
||||
}
|
||||
return connectionString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace Oqtane
|
||||
//add possibility to switch off swagger on production.
|
||||
_useSwagger = Configuration.GetSection("UseSwagger").Value != "false";
|
||||
|
||||
AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(env.ContentRootPath, "Data"));
|
||||
AppDomain.CurrentDomain.SetData(Constants.DataDirectory, Path.Combine(env.ContentRootPath, "Data"));
|
||||
|
||||
_env = env;
|
||||
}
|
||||
|
@ -12,25 +12,23 @@ namespace [Owner].[Module].Manager
|
||||
{
|
||||
public class [Module]Manager : MigratableModuleBase, IInstallable, IPortable
|
||||
{
|
||||
private I[Module]Repository _[Module]Repository;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly I[Module]Repository _[Module]Repository;
|
||||
private readonly IDBContextDependencies _DBContextDependencies;
|
||||
|
||||
public [Module]Manager(I[Module]Repository [Module]Repository, ITenantManager tenantManager, IHttpContextAccessor accessor)
|
||||
public [Module]Manager(I[Module]Repository [Module]Repository, IDBContextDependencies DBContextDependencies)
|
||||
{
|
||||
_[Module]Repository = [Module]Repository;
|
||||
_tenantManager = tenantManager;
|
||||
_accessor = accessor;
|
||||
_DBContextDependencies = DBContextDependencies;
|
||||
}
|
||||
|
||||
public bool Install(Tenant tenant, string version)
|
||||
{
|
||||
return Migrate(new [Module]Context(_tenantManager, _accessor), tenant, MigrationType.Up);
|
||||
return Migrate(new [Module]Context(_DBContextDependencies), tenant, MigrationType.Up);
|
||||
}
|
||||
|
||||
public bool Uninstall(Tenant tenant)
|
||||
{
|
||||
return Migrate(new [Module]Context(_tenantManager, _accessor), tenant, MigrationType.Down);
|
||||
return Migrate(new [Module]Context(_DBContextDependencies), tenant, MigrationType.Down);
|
||||
}
|
||||
|
||||
public string ExportModule(Module module)
|
||||
|
@ -11,7 +11,7 @@ namespace [Owner].[Module].Repository
|
||||
{
|
||||
public virtual DbSet<Models.[Module]> [Module] { get; set; }
|
||||
|
||||
public [Module]Context(ITenantManager tenantManager, IHttpContextAccessor accessor) : base(tenantManager, accessor)
|
||||
public [Module]Context(IDBContextDependencies DBContextDependencies) : base(DBContextDependencies) { }
|
||||
{
|
||||
// ContextBase handles multi-tenant database connections
|
||||
}
|
||||
|
Reference in New Issue
Block a user