Added IDatabase interface and refactored to use it to handle database type - updated Installer to dynamically add databases to selector
This commit is contained in:
parent
cbcfc88492
commit
3a032f401a
|
@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Providers;
|
using Oqtane.Providers;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
|
@ -85,6 +86,17 @@ namespace Oqtane.Client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dynamically register database providers
|
||||||
|
var databaseTypes = assembly.GetInterfaces<IDatabase>();
|
||||||
|
foreach (var databaseType in databaseTypes)
|
||||||
|
{
|
||||||
|
if (databaseType.AssemblyQualifiedName != null)
|
||||||
|
{
|
||||||
|
var serviceType = Type.GetType("Oqtane.Interfaces.IDatabase, Oqtane.Shared");
|
||||||
|
builder.Services.AddScoped(serviceType ?? databaseType, databaseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// register client startup services
|
// register client startup services
|
||||||
var startUps = assembly.GetInstances<IClientStartup>();
|
var startUps = assembly.GetInstances<IClientStartup>();
|
||||||
foreach (var startup in startUps)
|
foreach (var startup in startUps)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
@using Oqtane.Interfaces
|
||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
|
@ -5,6 +6,7 @@
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject IStringLocalizer<Installer> Localizer
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
|
@inject IEnumerable<IDatabase> Databases
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -25,9 +27,12 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select class="custom-select" @bind="@_databaseType">
|
<select class="custom-select" @bind="@_databaseType">
|
||||||
<option value="LocalDB">@Localizer["Local Database"]</option>
|
@{
|
||||||
<option value="SQLServer">@Localizer["SQL Server"]</option>
|
foreach (var database in Databases)
|
||||||
<option value="Sqlite">@Localizer["Sqlite"]</option>
|
{
|
||||||
|
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -148,8 +153,6 @@
|
||||||
private string _hostEmail = string.Empty;
|
private string _hostEmail = string.Empty;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private string _integratedSecurityDisplay = "display: none;";
|
private string _integratedSecurityDisplay = "display: none;";
|
||||||
private string _fileFieldsDisplay = "display: none;";
|
|
||||||
private string _serverFieldsDisplay = "display: none;";
|
|
||||||
private string _loadingDisplay = "display: none;";
|
private string _loadingDisplay = "display: none;";
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
@ -176,10 +179,12 @@
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
|
||||||
var connectionstring = "";
|
var connectionstring = "";
|
||||||
|
var fullyQualifiedType = "";
|
||||||
switch (_databaseType)
|
switch (_databaseType)
|
||||||
{
|
{
|
||||||
case "LocalDB":
|
case "LocalDB":
|
||||||
connectionstring = "Data Source=" + _serverName + ";AttachDbFilename=|DataDirectory|\\" + _databaseName + ".mdf;Initial Catalog=" + _databaseName + ";Integrated Security=SSPI;";
|
connectionstring = "Data Source=" + _serverName + ";AttachDbFilename=|DataDirectory|\\" + _databaseName + ".mdf;Initial Catalog=" + _databaseName + ";Integrated Security=SSPI;";
|
||||||
|
fullyQualifiedType = "Oqtane.Repository.Databases.LocalDbDatabase, Oqtane.Server";
|
||||||
break;
|
break;
|
||||||
case "SQLServer":
|
case "SQLServer":
|
||||||
connectionstring = "Data Source=" + _serverName + ";Initial Catalog=" + _databaseName + ";";
|
connectionstring = "Data Source=" + _serverName + ";Initial Catalog=" + _databaseName + ";";
|
||||||
|
@ -191,9 +196,11 @@
|
||||||
{
|
{
|
||||||
connectionstring += "User ID=" + _username + ";Password=" + _password;
|
connectionstring += "User ID=" + _username + ";Password=" + _password;
|
||||||
}
|
}
|
||||||
|
fullyQualifiedType = "Oqtane.Repository.Databases.SqlServerDatabase, Oqtane.Server";
|
||||||
break;
|
break;
|
||||||
case "Sqlite":
|
case "Sqlite":
|
||||||
connectionstring = "Data Source=" + _fileName;
|
connectionstring = "Data Source=" + _fileName;
|
||||||
|
fullyQualifiedType = "Oqtane.Repository.Databases.SqliteDatabase, Oqtane.Server";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +208,7 @@
|
||||||
|
|
||||||
var config = new InstallConfig
|
var config = new InstallConfig
|
||||||
{
|
{
|
||||||
DatabaseType = _databaseType,
|
DatabaseType = fullyQualifiedType,
|
||||||
ConnectionString = connectionstring,
|
ConnectionString = connectionstring,
|
||||||
Aliases = uri.Authority,
|
Aliases = uri.Authority,
|
||||||
HostEmail = _hostEmail,
|
HostEmail = _hostEmail,
|
||||||
|
@ -212,6 +219,8 @@
|
||||||
SiteName = Constants.DefaultSite
|
SiteName = Constants.DefaultSite
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var installation = await InstallationService.Install(config);
|
var installation = await InstallationService.Install(config);
|
||||||
if (installation.Success)
|
if (installation.Success)
|
||||||
{
|
{
|
||||||
|
|
16
Oqtane.Server/Databases/LocalDbDatabase.cs
Normal file
16
Oqtane.Server/Databases/LocalDbDatabase.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository.Databases
|
||||||
|
{
|
||||||
|
public class LocalDbDatabase : IDatabase
|
||||||
|
{
|
||||||
|
public string FriendlyName => "Local Database";
|
||||||
|
public string Name => "LocalDB";
|
||||||
|
|
||||||
|
public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||||
|
{
|
||||||
|
return optionsBuilder.UseSqlServer(connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
Oqtane.Server/Databases/SqlServerDatabase.cs
Normal file
17
Oqtane.Server/Databases/SqlServerDatabase.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository.Databases
|
||||||
|
{
|
||||||
|
public class SqlServerDatabase : IDatabase
|
||||||
|
{
|
||||||
|
public string FriendlyName => "SQL Server";
|
||||||
|
|
||||||
|
public string Name => "SqlServer";
|
||||||
|
|
||||||
|
public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||||
|
{
|
||||||
|
return optionsBuilder.UseSqlServer(connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
Oqtane.Server/Databases/SqliteDatabase.cs
Normal file
17
Oqtane.Server/Databases/SqliteDatabase.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository.Databases
|
||||||
|
{
|
||||||
|
public class SqliteDatabase : IDatabase
|
||||||
|
{
|
||||||
|
public string FriendlyName => Name;
|
||||||
|
|
||||||
|
public string Name => "Sqlite";
|
||||||
|
|
||||||
|
public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||||
|
{
|
||||||
|
return optionsBuilder.UseSqlite(connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
// ReSharper disable ConvertToUsingDeclaration
|
||||||
|
|
||||||
namespace Oqtane.Extensions
|
namespace Oqtane.Extensions
|
||||||
{
|
{
|
||||||
|
@ -7,16 +12,10 @@ namespace Oqtane.Extensions
|
||||||
{
|
{
|
||||||
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string databaseType, string connectionString)
|
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string databaseType, string connectionString)
|
||||||
{
|
{
|
||||||
switch (databaseType)
|
var type = Type.GetType(databaseType);
|
||||||
{
|
var database = Activator.CreateInstance(type) as IDatabase;
|
||||||
case "SqlServer":
|
|
||||||
optionsBuilder.UseSqlServer(connectionString);
|
|
||||||
|
|
||||||
break;
|
database.UseDatabase(optionsBuilder, connectionString);
|
||||||
case "Sqlite":
|
|
||||||
optionsBuilder.UseSqlite(connectionString);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return optionsBuilder;
|
return optionsBuilder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
@ -46,6 +47,17 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dynamically register database providers
|
||||||
|
var databaseTypes = assembly.GetInterfaces<IDatabase>();
|
||||||
|
foreach (var databaseType in databaseTypes)
|
||||||
|
{
|
||||||
|
if (databaseType.AssemblyQualifiedName != null)
|
||||||
|
{
|
||||||
|
var serviceType = Type.GetType("Oqtane.Interfaces.IDatabase, 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)
|
||||||
|
|
|
@ -234,7 +234,7 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases))
|
if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases))
|
||||||
{
|
{
|
||||||
using (var db = new InstallationContext(install.DatabaseType, NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey))))
|
using (var db = GetInstallationContext())
|
||||||
{
|
{
|
||||||
Tenant tenant;
|
Tenant tenant;
|
||||||
if (install.IsNewTenant)
|
if (install.IsNewTenant)
|
||||||
|
@ -274,6 +274,14 @@ namespace Oqtane.Infrastructure
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InstallationContext GetInstallationContext()
|
||||||
|
{
|
||||||
|
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
||||||
|
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
|
||||||
|
|
||||||
|
return new InstallationContext(databaseType, connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
private Installation MigrateTenants(InstallConfig install)
|
private Installation MigrateTenants(InstallConfig install)
|
||||||
{
|
{
|
||||||
var result = new Installation { Success = false, Message = string.Empty };
|
var result = new Installation { Success = false, Message = string.Empty };
|
||||||
|
@ -284,9 +292,7 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
|
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
|
||||||
|
|
||||||
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
using (var db = GetInstallationContext())
|
||||||
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
|
|
||||||
using (var db = new InstallationContext(databaseType, connectionString))
|
|
||||||
{
|
{
|
||||||
foreach (var tenant in db.Tenant.ToList())
|
foreach (var tenant in db.Tenant.ToList())
|
||||||
{
|
{
|
||||||
|
@ -347,9 +353,8 @@ 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);
|
||||||
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
using (var db = GetInstallationContext())
|
||||||
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
|
{
|
||||||
using (var db = new InstallationContext(databaseType, connectionString)) {
|
|
||||||
foreach (var tenant in db.Tenant.ToList())
|
foreach (var tenant in db.Tenant.ToList())
|
||||||
{
|
{
|
||||||
var index = Array.FindIndex(versions, item => item == moduleDefinition.Version);
|
var index = Array.FindIndex(versions, item => item == moduleDefinition.Version);
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Oqtane.Migrations
|
||||||
migrationBuilder.Sql(
|
migrationBuilder.Sql(
|
||||||
@"
|
@"
|
||||||
UPDATE Tenant
|
UPDATE Tenant
|
||||||
SET DBType = 'SqlServer'
|
SET DBType = 'Oqtane.Repository.Databases.SqlServerDatabase, Oqtane.Server'
|
||||||
");
|
");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ namespace Oqtane.Migrations.Extensions
|
||||||
{
|
{
|
||||||
return table.Column<int>(name: name, nullable: false)
|
return table.Column<int>(name: name, nullable: false)
|
||||||
.Annotation("SqlServer:Identity", "1, 1")
|
.Annotation("SqlServer:Identity", "1, 1")
|
||||||
.Annotation("Sqlite:Autoincrement", true);
|
.Annotation("Sqlite:Autoincrement", true)
|
||||||
|
.Annotation("MySql:ValueGeneratedOnAdd", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OperationBuilder<AddColumnOperation> AddBooleanColumn(this ColumnsBuilder table, string name, bool nullable = false)
|
public static OperationBuilder<AddColumnOperation> AddBooleanColumn(this ColumnsBuilder table, string name, bool nullable = false)
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Models;
|
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||||
|
|
13
Oqtane.Shared/Interfaces/IDatabase.cs
Normal file
13
Oqtane.Shared/Interfaces/IDatabase.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Oqtane.Interfaces
|
||||||
|
{
|
||||||
|
public interface IDatabase
|
||||||
|
{
|
||||||
|
public string FriendlyName { get; }
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString);
|
||||||
|
}
|
||||||
|
}
|
9
Oqtane.Shared/Models/Database.cs
Normal file
9
Oqtane.Shared/Models/Database.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Oqtane.Models
|
||||||
|
{
|
||||||
|
public class Database
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Text.Json" Version="5.0.1" />
|
<PackageReference Include="System.Text.Json" Version="5.0.1" />
|
||||||
|
|
Loading…
Reference in New Issue
Block a user