migrate database providers to core framework

This commit is contained in:
sbwalker
2025-08-14 15:19:52 -04:00
parent b553b16049
commit b5a9c32c3e
20 changed files with 120 additions and 276 deletions

View File

@ -10,10 +10,10 @@ namespace Oqtane.Controllers
[Route(ControllerRoutes.ApiRoute)]
public class DatabaseController : Controller
{
private IOptions<List<Database>> _databaseOptions;
private IOptions<List<Models.Database>> _databaseOptions;
private IConfigManager _config;
public DatabaseController(IOptions<List<Database>> databaseOptions, IConfigManager config)
public DatabaseController(IOptions<List<Models.Database>> databaseOptions, IConfigManager config)
{
_databaseOptions = databaseOptions;
_config = config;
@ -21,7 +21,7 @@ namespace Oqtane.Controllers
// GET: api/<controller>
[HttpGet]
public IEnumerable<Database> Get()
public IEnumerable<Models.Database> Get()
{
var databases = _databaseOptions.Value;
var master = _config.GetSetting(SettingKeys.DatabaseSection, SettingKeys.DatabaseTypeKey, "");

View File

@ -0,0 +1,114 @@
using System.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
using MySql.Data.MySqlClient;
using Oqtane.Databases;
namespace Oqtane.Database.MySQL
{
public class MySQLDatabase : DatabaseBase
{
private static string _friendlyName => "MySQL";
private static string _name => "MySQL";
static MySQLDatabase()
{
Initialize(typeof(MySQLDatabase));
}
public MySQLDatabase() :base(_name, _friendlyName) { }
public override string Provider => "Pomelo.EntityFrameworkCore.MySql";
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
{
return table.Column<int>(name: name, nullable: false).Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
}
public override string ConcatenateSql(params string[] values)
{
var returnValue = "CONCAT(";
for (var i = 0; i < values.Length; i++)
{
if (i > 0)
{
returnValue += ",";
}
returnValue += values[i];
}
returnValue += ")";
return returnValue;
}
public override int ExecuteNonQuery(string connectionString, string query)
{
var conn = new MySqlConnection(connectionString);
var cmd = conn.CreateCommand();
using (conn)
{
PrepareCommand(conn, cmd, query);
var val = -1;
try
{
val = cmd.ExecuteNonQuery();
}
catch
{
// an error occurred executing the query
}
return val;
}
}
public override IDataReader ExecuteReader(string connectionString, string query)
{
var conn = new MySqlConnection(connectionString);
var cmd = conn.CreateCommand();
PrepareCommand(conn, cmd, query);
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr;
}
public override string DelimitName(string name)
{
return $"`{name}`";
}
public override string RewriteValue(object value)
{
var type = value.GetType().Name;
if (type == "DateTime")
{
return $"'{value}'";
}
if (type == "Boolean")
{
return (bool)value ? "1" : "0"; // MySQL uses 1/0 for boolean values
}
return value.ToString();
}
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
{
return optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
private void PrepareCommand(MySqlConnection conn, MySqlCommand cmd, string query)
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
cmd.Connection = conn;
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Internal;
using Oqtane.Migrations.Framework;
using Oqtane.Models;
// ReSharper disable ClassNeverInstantiated.Global
namespace Oqtane.Database.PostgreSQL
{
public class HistoryRepository : NpgsqlHistoryRepository
{
private string _appliedDateColumnName = "applied_date";
private string _appliedVersionColumnName = "applied_version";
private MigrationHistoryTable _migrationHistoryTable;
public HistoryRepository(HistoryRepositoryDependencies dependencies) : base(dependencies)
{
_migrationHistoryTable = new MigrationHistoryTable
{
TableName = TableName,
TableSchema = TableSchema,
MigrationIdColumnName = MigrationIdColumnName,
ProductVersionColumnName = ProductVersionColumnName,
AppliedVersionColumnName = _appliedVersionColumnName,
AppliedDateColumnName = _appliedDateColumnName
};
}
protected override void ConfigureTable(EntityTypeBuilder<HistoryRow> history)
{
base.ConfigureTable(history);
history.Property<string>(_appliedVersionColumnName).HasMaxLength(10);
history.Property<DateTime>(_appliedDateColumnName);
}
public override string GetInsertScript(HistoryRow row)
{
if (row == null)
{
throw new ArgumentNullException(nameof(row));
}
return MigrationUtils.BuildInsertScript(row, Dependencies, _migrationHistoryTable);
}
}
}

View File

@ -0,0 +1,165 @@
using System;
using System.Data;
using System.Globalization;
using EFCore.NamingConventions.Internal;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
using Npgsql;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Oqtane.Databases;
namespace Oqtane.Database.PostgreSQL
{
public class PostgreSQLDatabase : DatabaseBase
{
private static string _friendlyName => "PostgreSQL";
private static string _name => "PostgreSQL";
private readonly INameRewriter _rewriter;
static PostgreSQLDatabase()
{
Initialize(typeof(PostgreSQLDatabase));
}
public PostgreSQLDatabase() : base(_name, _friendlyName)
{
_rewriter = new SnakeCaseNameRewriter(CultureInfo.InvariantCulture);
}
public override string Provider => "Npgsql.EntityFrameworkCore.PostgreSQL";
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
{
return table.Column<int>(name: name, nullable: false).Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn);
}
public override string ConcatenateSql(params string[] values)
{
var returnValue = String.Empty;
for (var i = 0; i < values.Length; i++)
{
if (i > 0)
{
returnValue += " || ";
}
returnValue += values[i];
}
return returnValue;
}
public override int ExecuteNonQuery(string connectionString, string query)
{
var conn = new NpgsqlConnection(connectionString);
var cmd = conn.CreateCommand();
using (conn)
{
PrepareCommand(conn, cmd, query);
var val = -1;
try
{
val = cmd.ExecuteNonQuery();
}
catch
{
// an error occurred executing the query
}
return val;
}
}
public override IDataReader ExecuteReader(string connectionString, string query)
{
var conn = new NpgsqlConnection(connectionString);
var cmd = conn.CreateCommand();
PrepareCommand(conn, cmd, query);
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr;
}
public override string RewriteName(string name)
{
return _rewriter.RewriteName(name);
}
public override string DelimitName(string name)
{
return $"\"{name}\"";
}
public override string RewriteValue(object value)
{
var type = value.GetType().Name;
if (type == "DateTime")
{
return $"'{value}'";
}
if (type == "Boolean")
{
return (bool)value ? "true" : "false"; // PostgreSQL uses true/false for boolean values
}
return value.ToString();
}
public override void UpdateIdentityStoreTableNames(ModelBuilder builder)
{
foreach(var entity in builder.Model.GetEntityTypes())
{
var tableName = entity.GetTableName();
if (tableName.StartsWith("AspNetUser"))
{
// replace table name
entity.SetTableName(RewriteName(entity.GetTableName()));
// replace column names
foreach(var property in entity.GetProperties())
{
property.SetColumnName(RewriteName(property.Name));
}
// replace key names
foreach(var key in entity.GetKeys())
{
key.SetName(RewriteName(key.GetName()));
}
// replace foreign key names
foreach (var key in entity.GetForeignKeys())
{
key.PrincipalKey.SetName(RewriteName(key.PrincipalKey.GetName()));
}
// replace index names
foreach (var index in entity.GetIndexes())
{
index.SetDatabaseName(RewriteName(index.GetDatabaseName()));
}
}
}
}
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
{
return optionsBuilder.UseNpgsql(connectionString)
.UseSnakeCaseNamingConvention()
.ReplaceService<IHistoryRepository, HistoryRepository>();
}
private void PrepareCommand(NpgsqlConnection conn, NpgsqlCommand cmd, string query)
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
cmd.Connection = conn;
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.SqlServer.Migrations.Internal;
using Oqtane.Migrations.Framework;
using Oqtane.Models;
// ReSharper disable ClassNeverInstantiated.Global
namespace Oqtane.Database.SqlServer
{
public class HistoryRepository : SqlServerHistoryRepository
{
private string _appliedDateColumnName = "AppliedDate";
private string _appliedVersionColumnName = "AppliedVersion";
private MigrationHistoryTable _migrationHistoryTable;
public HistoryRepository(HistoryRepositoryDependencies dependencies) : base(dependencies)
{
_migrationHistoryTable = new MigrationHistoryTable
{
TableName = TableName,
TableSchema = TableSchema,
MigrationIdColumnName = MigrationIdColumnName,
ProductVersionColumnName = ProductVersionColumnName,
AppliedVersionColumnName = _appliedVersionColumnName,
AppliedDateColumnName = _appliedDateColumnName
};
}
protected override void ConfigureTable(EntityTypeBuilder<HistoryRow> history)
{
base.ConfigureTable(history);
history.Property<string>(_appliedVersionColumnName).HasMaxLength(10);
history.Property<DateTime>(_appliedDateColumnName);
}
public override string GetInsertScript(HistoryRow row)
{
if (row == null)
{
throw new ArgumentNullException(nameof(row));
}
return MigrationUtils.BuildInsertScript(row, Dependencies, _migrationHistoryTable);
}
}
}

View File

@ -0,0 +1,120 @@
using System;
using System.Data;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
using Oqtane.Databases;
namespace Oqtane.Database.SqlServer
{
public class SqlServerDatabase : DatabaseBase
{
private static string _friendlyName => "SQL Server";
private static string _name => "SqlServer";
static SqlServerDatabase()
{
Initialize(typeof(SqlServerDatabase));
}
public SqlServerDatabase() : base(_name, _friendlyName)
{
}
public override string Provider => "Microsoft.EntityFrameworkCore.SqlServer";
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
{
return table.Column<int>(name: name, nullable: false).Annotation("SqlServer:Identity", "1, 1");
}
public override void AlterStringColumn(MigrationBuilder builder, string name, string table, int length, bool nullable, bool unicode, string index)
{
var elements = index.Split(':', StringSplitOptions.RemoveEmptyEntries);
if (elements.Length != 0)
{
builder.DropIndex(elements[0], table);
}
builder.AlterColumn<string>(name, table, maxLength: length, nullable: nullable, unicode: unicode);
if (elements.Length != 0)
{
var columns = elements[1].Split(',');
builder.CreateIndex(elements[0], table, columns, null, bool.Parse(elements[2]), null);
}
}
public override string DelimitName(string name)
{
return $"[{name}]";
}
public override string RewriteValue(object value)
{
var type = value.GetType().Name;
if (type == "DateTime")
{
return $"'{value}'";
}
if (type == "Boolean")
{
return (bool)value ? "1" : "0"; // SQL Server uses 1/0 for boolean values
}
return value.ToString();
}
public override int ExecuteNonQuery(string connectionString, string query)
{
var conn = new SqlConnection(FormatConnectionString(connectionString));
var cmd = conn.CreateCommand();
using (conn)
{
PrepareCommand(conn, cmd, query);
var val = -1;
try
{
val = cmd.ExecuteNonQuery();
}
catch
{
// an error occurred executing the query
}
return val;
}
}
public override IDataReader ExecuteReader(string connectionString, string query)
{
var conn = new SqlConnection(FormatConnectionString(connectionString));
var cmd = conn.CreateCommand();
PrepareCommand(conn, cmd, query);
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr;
}
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
{
return optionsBuilder.UseSqlServer(connectionString)
.ReplaceService<IHistoryRepository, HistoryRepository>();
}
private string FormatConnectionString(string connectionString)
{
return connectionString.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString());
}
private void PrepareCommand(SqlConnection conn, SqlCommand cmd, string query)
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
cmd.Connection = conn;
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Sqlite.Migrations.Internal;
using Oqtane.Migrations.Framework;
using Oqtane.Models;
// ReSharper disable ClassNeverInstantiated.Global
namespace Oqtane.Database.Sqlite
{
public class HistoryRepository : SqliteHistoryRepository
{
private string _appliedDateColumnName = "AppliedDate";
private string _appliedVersionColumnName = "AppliedVersion";
private MigrationHistoryTable _migrationHistoryTable;
public HistoryRepository(HistoryRepositoryDependencies dependencies) : base(dependencies)
{
_migrationHistoryTable = new MigrationHistoryTable
{
TableName = TableName,
TableSchema = TableSchema,
MigrationIdColumnName = MigrationIdColumnName,
ProductVersionColumnName = ProductVersionColumnName,
AppliedVersionColumnName = _appliedVersionColumnName,
AppliedDateColumnName = _appliedDateColumnName
};
}
protected override void ConfigureTable(EntityTypeBuilder<HistoryRow> history)
{
base.ConfigureTable(history);
history.Property<string>(_appliedVersionColumnName).HasMaxLength(10);
history.Property<DateTime>(_appliedDateColumnName);
}
public override string GetInsertScript(HistoryRow row)
{
if (row == null)
{
throw new ArgumentNullException(nameof(row));
}
return MigrationUtils.BuildInsertScript(row, Dependencies, _migrationHistoryTable);
}
}
}

View File

@ -0,0 +1,123 @@
using System;
using System.Data;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
using Oqtane.Databases;
namespace Oqtane.Database.Sqlite
{
public class SqliteDatabase : DatabaseBase
{
private static string _friendlyName => "SQLite";
private static string _name => "Sqlite";
static SqliteDatabase()
{
Initialize(typeof(SqliteDatabase));
}
public SqliteDatabase() :base(_name, _friendlyName) { }
public override string Provider => "Microsoft.EntityFrameworkCore.Sqlite";
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
{
return table.Column<int>(name: name, nullable: false).Annotation("Sqlite:Autoincrement", true);
}
public override void DropColumn(MigrationBuilder builder, string name, string table)
{
// not implemented as SQLite does not support dropping columns
}
public override void AlterStringColumn(MigrationBuilder builder, string name, string table, int length, bool nullable, bool unicode, string index)
{
// not implemented as SQLite does not support altering columns
}
public override string ConcatenateSql(params string[] values)
{
var returnValue = String.Empty;
for (var i = 0; i < values.Length; i++)
{
if (i > 0)
{
returnValue += " || ";
}
returnValue += values[i];
}
return returnValue;
}
public override int ExecuteNonQuery(string connectionString, string query)
{
var conn = new SqliteConnection(connectionString);
var cmd = conn.CreateCommand();
using (conn)
{
PrepareCommand(conn, cmd, query);
var val = -1;
try
{
val = cmd.ExecuteNonQuery();
}
catch
{
// an error occurred executing the query
}
return val;
}
}
public override IDataReader ExecuteReader(string connectionString, string query)
{
var conn = new SqliteConnection(connectionString);
var cmd = conn.CreateCommand();
PrepareCommand(conn, cmd, query);
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr;
}
public override string DelimitName(string name)
{
return $"\"{name}\"";
}
public override string RewriteValue(object value)
{
var type = value.GetType().Name;
if (type == "DateTime")
{
return $"'{value}'";
}
if (type == "Boolean")
{
return (bool)value ? "1" : "0"; // SQLite uses 1/0 for boolean values
}
return value.ToString();
}
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
{
return optionsBuilder.UseSqlite(connectionString)
.ReplaceService<IHistoryRepository, HistoryRepository>();
}
private void PrepareCommand(SqliteConnection conn, SqliteCommand cmd, string query)
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
cmd.Connection = conn;
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
}
}
}

View File

@ -663,7 +663,7 @@ namespace Oqtane.Infrastructure
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
Oqtane.Databases.Interfaces.IDatabase database = null;
Databases.Interfaces.IDatabase database = null;
if (!string.IsNullOrEmpty(databaseType))
{
var type = Type.GetType(databaseType);
@ -744,32 +744,34 @@ namespace Oqtane.Infrastructure
private void ValidateConfiguration()
{
if (_configManager.GetSetting(SettingKeys.DatabaseSection, SettingKeys.DatabaseTypeKey, "") == "")
var defaultDatabaseType = _configManager.GetSetting(SettingKeys.DatabaseSection, SettingKeys.DatabaseTypeKey, "");
if (defaultDatabaseType == "" || defaultDatabaseType.Contains(", Oqtane.Database."))
{
_configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", Constants.DefaultDBType, true);
// DefaultDBType migrated to Oqtane.Server in 6.1.5
defaultDatabaseType = defaultDatabaseType.Substring(0, defaultDatabaseType.IndexOf(", ")) + ", Oqtane.Server";
_configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", defaultDatabaseType, true);
}
var updateAvailableDatabases = false;
if (!_configManager.GetSection(SettingKeys.AvailableDatabasesSection).Exists())
{
string databases = "[";
databases += "{ \"Name\": \"LocalDB\", \"ControlType\": \"Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },";
databases += "{ \"Name\": \"SQL Server\", \"ControlType\": \"Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },";
databases += "{ \"Name\": \"SQLite\", \"ControlType\": \"Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Database.Sqlite\" },";
databases += "{ \"Name\": \"MySQL\", \"ControlType\": \"Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.MySQL.MySQLDatabase, Oqtane.Database.MySQL\" },";
databases += "{ \"Name\": \"PostgreSQL\", \"ControlType\": \"Oqtane.Installer.Controls.PostgreSQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Database.PostgreSQL\" }";
databases += "]";
_configManager.AddOrUpdateSetting(SettingKeys.AvailableDatabasesSection, databases, true);
updateAvailableDatabases = true;
}
var availabledatabases = _configManager.GetSection(SettingKeys.AvailableDatabasesSection).GetChildren();
if (!availabledatabases.Any(item => item.GetSection("Name").Value == "Azure SQL"))
else
{
// available databases migrated to Oqtane.Server in 6.1.5
updateAvailableDatabases = !_configManager.GetSection(SettingKeys.AvailableDatabasesSection).GetChildren()
.Any(item => item.GetSection("DBType").Value == "Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server");
}
if (updateAvailableDatabases)
{
// Azure SQL added in 6.1.2
string databases = "[";
foreach (var database in availabledatabases)
{
databases += "{ " + $"\"Name\": \"{database["Name"]}\", \"ControlType\": \"{database["ControlType"]}\", \"DBTYpe\": \"{database["DBType"]}\"" + " },";
}
databases += "{ \"Name\": \"Azure SQL\", \"ControlType\": \"Oqtane.Installer.Controls.AzureSqlConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" }";
databases += "{ \"Name\": \"LocalDB\", \"ControlType\": \"Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client\", \"DBType\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server\" },";
databases += "{ \"Name\": \"SQL Server\", \"ControlType\": \"Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client\", \"DBType\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server\" },";
databases += "{ \"Name\": \"SQLite\", \"ControlType\": \"Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client\", \"DBType\": \"Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Server\" },";
databases += "{ \"Name\": \"MySQL\", \"ControlType\": \"Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client\", \"DBType\": \"Oqtane.Database.MySQL.MySQLDatabase, Oqtane.Server\" },";
databases += "{ \"Name\": \"PostgreSQL\", \"ControlType\": \"Oqtane.Installer.Controls.PostgreSQLConfig, Oqtane.Client\", \"DBType\": \"Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Server\" },";
databases += "{ \"Name\": \"Azure SQL\", \"ControlType\": \"Oqtane.Installer.Controls.AzureSqlConfig, Oqtane.Client\", \"DBType\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server\" }";
databases += "]";
_configManager.AddOrUpdateSetting(SettingKeys.AvailableDatabasesSection, databases, true);
}

View File

@ -84,6 +84,9 @@ namespace Oqtane.Infrastructure
case "6.1.1":
Upgrade_6_1_1(tenant, scope);
break;
case "6.1.5":
Upgrade_6_1_5(tenant, scope);
break;
}
}
}
@ -537,6 +540,24 @@ namespace Oqtane.Infrastructure
AddPagesToSites(scope, tenant, pageTemplates);
}
private void Upgrade_6_1_5(Tenant tenant, IServiceScope scope)
{
// remove Database Providers which were moved to Oqtane.Server
string[] assemblies = {
"Oqtane.Database.MySQL.dll",
"Oqtane.Database.MySQL.pdb",
"Oqtane.Database.PostgreSQL.dll",
"Oqtane.Database.PostgreSQL.pdb",
"Oqtane.Database.Sqlite.dll",
"Oqtane.Database.Sqlite.pdb",
"Oqtane.Database.SqlServer.dll",
"Oqtane.Database.SqlServer.pdb"
};
RemoveAssemblies(tenant, assemblies, "6.1.5");
}
private void AddPagesToSites(IServiceScope scope, Tenant tenant, List<PageTemplate> pageTemplates)
{
var tenants = scope.ServiceProvider.GetRequiredService<ITenantManager>();

View File

@ -0,0 +1,33 @@
using System.Data;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Databases.Interfaces;
using Oqtane.Migrations.EntityBuilders;
using Oqtane.Repository;
namespace Oqtane.Migrations.Master
{
[DbContext(typeof(MasterDBContext))]
[Migration("Master.06.01.05.01")]
public class UpdateTenantDBType : MultiDatabaseMigration
{
public UpdateTenantDBType(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
// database providers moved to oqtane.server
var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase);
tenantEntityBuilder.UpdateData("DBType", "'Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server'", $"{DelimitName(RewriteName("DBType"))} = 'Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer'");
tenantEntityBuilder.UpdateData("DBType", "'Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Server'", $"{DelimitName(RewriteName("DBType"))} = 'Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Database.Sqlite'");
tenantEntityBuilder.UpdateData("DBType", "'Oqtane.Database.MySQL.MySQLDatabase, Oqtane.Server'", $"{DelimitName(RewriteName("DBType"))} = 'Oqtane.Database.MySQL.MySQLDatabase, Oqtane.Database.MySQL'");
tenantEntityBuilder.UpdateData("DBType", "'Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Server'", $"{DelimitName(RewriteName("DBType"))} = 'Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Database.PostgreSQL'");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// not implemented
}
}
}

View File

@ -33,6 +33,7 @@
<EmbeddedResource Include="Scripts\MigrateMaster.sql" />
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.8" />
@ -44,33 +45,51 @@
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.8" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.8" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
<PackageReference Include="HtmlAgilityPack" Version="1.12.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
<PackageReference Include="MailKit" Version="4.13.0" />
</ItemGroup>
<ItemGroup>
<!-- MySQL Database Provider Dependencies -->
<PackageReference Include="MySql.Data" Version="9.4.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0-preview.3.efcore.9.0.0" />
<!-- PostgreSQL Database Provider Dependencies -->
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.8" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<!-- SQLite Database Provider Dependencies -->
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.8" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.8" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.1" />
<!-- SQL Server Database Provider Dependencies -->
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
</ItemGroup>
<!-- Suppress EF Core internal warnings for Database Providers -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;EF1001;AD0001;NU1608</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;EF1001;AD0001</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<ModuleTemplateFiles Include="$(ProjectDir)wwwroot\Modules\Templates\**\*.*" />
<ThemeTemplateFiles Include="$(ProjectDir)wwwroot\Themes\Templates\**\*.*" />
<MySQLFiles Include="$(OutputPath)Oqtane.Database.MySQL.dll;$(OutputPath)Oqtane.Database.MySQL.pdb;$(OutputPath)Pomelo.EntityFrameworkCore.MySql.dll;$(OutputPath)MySql.Data.dll" />
<PostgreSQLFiles Include="$(OutputPath)Oqtane.Database.PostgreSQL.dll;$(OutputPath)Oqtane.Database.PostgreSQL.pdb;$(OutputPath)EFCore.NamingConventions.dll;$(OutputPath)Npgsql.EntityFrameworkCore.PostgreSQL.dll;$(OutputPath)Npgsql.dll" />
<SqliteFiles Include="$(OutputPath)Oqtane.Database.Sqlite.dll;$(OutputPath)Oqtane.Database.Sqlite.pdb;$(OutputPath)Microsoft.EntityFrameworkCore.Sqlite.dll" />
<SqlServerFiles Include="$(OutputPath)Oqtane.Database.SqlServer.dll;$(OutputPath)Oqtane.Database.SqlServer.pdb;$(OutputPath)Microsoft.EntityFrameworkCore.SqlServer.dll" />
</ItemGroup>
<Target Name="AddPayloadsFolder" AfterTargets="Publish">
<Copy SourceFiles="@(ModuleTemplateFiles)" DestinationFiles="@(ModuleTemplateFiles->'$(PublishDir)wwwroot\Modules\Templates\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
<Copy SourceFiles="@(ThemeTemplateFiles)" DestinationFiles="@(ThemeTemplateFiles->'$(PublishDir)wwwroot\Themes\Templates\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
<Copy SourceFiles="@(MySQLFiles)" DestinationFiles="@(MySQLFiles->'$(PublishDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
<Copy SourceFiles="@(PostgreSQLFiles)" DestinationFiles="@(PostgreSQLFiles->'$(PublishDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
<Copy SourceFiles="@(SqliteFiles)" DestinationFiles="@(SqliteFiles->'$(PublishDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
<Copy SourceFiles="@(SqlServerFiles)" DestinationFiles="@(SqlServerFiles->'$(PublishDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
</Target>
<ItemGroup>
<!-- extends watching group to include *.dll files and exclude the ones cause an infinite loop -->
<Watch Include="**\*.dll" Exclude="**\Microsoft.EntityFrameworkCore.*.dll;**\Oqtane.Database.*.dll;" />

View File

@ -69,7 +69,7 @@ namespace Oqtane
// register localization services
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddOptions<List<Database>>().Bind(Configuration.GetSection(SettingKeys.AvailableDatabasesSection));
services.AddOptions<List<Models.Database>>().Bind(Configuration.GetSection(SettingKeys.AvailableDatabasesSection));
// register scoped core services
services.AddScoped<IAuthorizationHandler, PermissionHandler>()