Added support for migrating existing Oqtane installations from DbUp to Migrations. Also added a Migration for version 2.0.2, and set current version to 2.1.0
This commit is contained in:
parent
d12b18350f
commit
8c45b7e42f
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
@ -75,7 +76,13 @@ namespace Oqtane.Infrastructure
|
||||||
if (install == null)
|
if (install == null)
|
||||||
{
|
{
|
||||||
// startup or silent installation
|
// startup or silent installation
|
||||||
install = new InstallConfig { ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey), TenantName = TenantNames.Master, IsNewTenant = false };
|
install = new InstallConfig
|
||||||
|
{
|
||||||
|
ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey),
|
||||||
|
TenantName = TenantNames.Master,
|
||||||
|
DatabaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey],
|
||||||
|
IsNewTenant = false
|
||||||
|
};
|
||||||
|
|
||||||
if (!IsInstalled())
|
if (!IsInstalled())
|
||||||
{
|
{
|
||||||
|
@ -207,6 +214,7 @@ namespace Oqtane.Infrastructure
|
||||||
using (var scope = _serviceScopeFactory.CreateScope())
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
||||||
|
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -214,6 +222,10 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
using (var masterDbContext = new MasterDBContext(new DbContextOptions<MasterDBContext>(), dbConfig))
|
using (var masterDbContext = new MasterDBContext(new DbContextOptions<MasterDBContext>(), dbConfig))
|
||||||
{
|
{
|
||||||
|
if (IsInstalled() && (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB"))
|
||||||
|
{
|
||||||
|
UpgradeSqlServer(sql, install.ConnectionString, true);
|
||||||
|
}
|
||||||
// Push latest model into database
|
// Push latest model into database
|
||||||
masterDbContext.Database.Migrate();
|
masterDbContext.Database.Migrate();
|
||||||
result.Success = true;
|
result.Success = true;
|
||||||
|
@ -303,14 +315,6 @@ namespace Oqtane.Infrastructure
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstallationContext GetInstallationContext(IEnumerable<IOqtaneDatabase> databases)
|
|
||||||
{
|
|
||||||
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
|
||||||
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
|
|
||||||
|
|
||||||
return new InstallationContext(databases.Single(d => d.Name == 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 };
|
||||||
|
@ -321,6 +325,7 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
|
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
|
||||||
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
||||||
|
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
|
||||||
|
|
||||||
using (var db = GetInstallationContext(databases))
|
using (var db = GetInstallationContext(databases))
|
||||||
{
|
{
|
||||||
|
@ -328,9 +333,14 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dbConfig = new DbConfig(null, null, databases) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType};
|
var dbConfig = new DbConfig(null, null, databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType};
|
||||||
using (var tenantDbContext = new TenantDBContext(dbConfig, null))
|
using (var tenantDbContext = new TenantDBContext(dbConfig, null))
|
||||||
{
|
{
|
||||||
|
if (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB")
|
||||||
|
{
|
||||||
|
UpgradeSqlServer(sql, tenant.DBConnectionString, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Push latest model into database
|
// Push latest model into database
|
||||||
tenantDbContext.Database.Migrate();
|
tenantDbContext.Database.Migrate();
|
||||||
result.Success = true;
|
result.Success = true;
|
||||||
|
@ -551,36 +561,6 @@ namespace Oqtane.Infrastructure
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string NormalizeConnectionString(string connectionString)
|
|
||||||
{
|
|
||||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
|
||||||
connectionString = connectionString.Replace("|DataDirectory|", dataDirectory);
|
|
||||||
return connectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string DenormalizeConnectionString(string connectionString)
|
|
||||||
{
|
|
||||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
|
||||||
connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|");
|
|
||||||
return connectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateConnectionString(string connectionString)
|
|
||||||
{
|
|
||||||
connectionString = DenormalizeConnectionString(connectionString);
|
|
||||||
if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString)
|
|
||||||
{
|
|
||||||
AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString);
|
|
||||||
_config.Reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateDatabaseType(string databaseType)
|
|
||||||
{
|
|
||||||
AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType);
|
|
||||||
_config.Reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddOrUpdateAppSetting<T>(string sectionPathKey, T value)
|
public void AddOrUpdateAppSetting<T>(string sectionPathKey, T value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -600,6 +580,36 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string DenormalizeConnectionString(string connectionString)
|
||||||
|
{
|
||||||
|
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||||
|
connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|");
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InstallationContext GetInstallationContext(IEnumerable<IOqtaneDatabase> databases)
|
||||||
|
{
|
||||||
|
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
||||||
|
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
|
||||||
|
|
||||||
|
return new InstallationContext(databases.Single(d => d.Name == databaseType), connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetInstallationConfig(string key, string defaultValue)
|
||||||
|
{
|
||||||
|
var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue);
|
||||||
|
// double fallback to default value - allow hold sample keys in config
|
||||||
|
if (string.IsNullOrEmpty(value)) value = defaultValue;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NormalizeConnectionString(string connectionString)
|
||||||
|
{
|
||||||
|
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||||
|
connectionString = connectionString.Replace("|DataDirectory|", dataDirectory);
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
private void SetValueRecursively<T>(string sectionPathKey, dynamic jsonObj, T value)
|
private void SetValueRecursively<T>(string sectionPathKey, dynamic jsonObj, T value)
|
||||||
{
|
{
|
||||||
// split the string at the first ':' character
|
// split the string at the first ':' character
|
||||||
|
@ -619,12 +629,27 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetInstallationConfig(string key, string defaultValue)
|
public void UpdateConnectionString(string connectionString)
|
||||||
{
|
{
|
||||||
var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue);
|
connectionString = DenormalizeConnectionString(connectionString);
|
||||||
// double fallback to default value - allow hold sample keys in config
|
if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString)
|
||||||
if (string.IsNullOrEmpty(value)) value = defaultValue;
|
{
|
||||||
return value;
|
AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString);
|
||||||
|
_config.Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateDatabaseType(string databaseType)
|
||||||
|
{
|
||||||
|
AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType);
|
||||||
|
_config.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpgradeSqlServer(ISqlRepository sql, string connectionString, bool isMaster)
|
||||||
|
{
|
||||||
|
var script = (isMaster) ? "MigrateMaster.sql" : "MigrateTenant.sql";
|
||||||
|
|
||||||
|
sql.ExecuteScript(connectionString, Assembly.GetExecutingAssembly(), script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs
Normal file
34
Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.00.02.01")]
|
||||||
|
|
||||||
|
public class AddSiteGuidToSite : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddSiteGuidToSite(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Add Column to Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.AddStringColumn("SiteGuid", 36, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Column from Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.DropColumn("SiteGuid");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.01.00.00")]
|
||||||
|
|
||||||
|
public class AddAppVersionsTable : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddAppVersionsTable(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Create AppVersions table
|
||||||
|
var appVersionsEntityBuilder = new AppVersionsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
appVersionsEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Finish SqlServer Migration from DbUp
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
//Version 1.0.0
|
||||||
|
InsertVersion(migrationBuilder, "01.00.00", "Oqtane.Scripts.Master.00.09.00.00.sql");
|
||||||
|
|
||||||
|
//Version 1.0.1
|
||||||
|
InsertVersion(migrationBuilder, "01.00.01", "Oqtane.Scripts.Master.01.00.01.00.sql");
|
||||||
|
|
||||||
|
//Version 1.0.2
|
||||||
|
InsertVersion(migrationBuilder, "01.00.02", "Oqtane.Scripts.Tenant.01.00.02.01.sql");
|
||||||
|
|
||||||
|
//Version 2.0.0
|
||||||
|
InsertVersion(migrationBuilder, "02.00.00", "Oqtane.Scripts.Tenant.02.00.00.01.sql");
|
||||||
|
|
||||||
|
//Version 2.0.1
|
||||||
|
InsertVersion(migrationBuilder, "02.00.01", "Oqtane.Scripts.Tenant.02.00.01.03.sql");
|
||||||
|
|
||||||
|
//Version 2.0.2
|
||||||
|
InsertVersion(migrationBuilder, "02.00.02", "Oqtane.Scripts.Tenant.02.00.02.01.sql");
|
||||||
|
|
||||||
|
//Drop SchemaVersions
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
DROP TABLE SchemaVersions
|
||||||
|
END");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Version 2.1.0
|
||||||
|
migrationBuilder.Sql($@"
|
||||||
|
INSERT INTO AppVersions(Version, AppliedDate)
|
||||||
|
VALUES('02.01.00', '{DateTime.UtcNow:u}')
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InsertVersion(MigrationBuilder migrationBuilder, string version, string scriptName)
|
||||||
|
{
|
||||||
|
migrationBuilder.Sql($@"
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO AppVersions(Version, AppliedDate)
|
||||||
|
SELECT Version = '{version}', Applied As AppliedDate
|
||||||
|
FROM SchemaVersions
|
||||||
|
WHERE ScriptName = '{scriptName}'
|
||||||
|
END
|
||||||
|
");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class AppVersionsEntityBuilder : BaseEntityBuilder<AppVersionsEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "AppVersions";
|
||||||
|
private readonly PrimaryKey<AppVersionsEntityBuilder> _primaryKey = new("PK_AppVersions", x => x.Id);
|
||||||
|
|
||||||
|
public AppVersionsEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AppVersionsEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
Id = AddAutoIncrementColumn(table,"Id");
|
||||||
|
Version = AddStringColumn(table,"Version", 10);
|
||||||
|
AppliedDate = AddDateTimeColumn(table,"AppliedDate");
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Id { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Version { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> AppliedDate { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,29 +83,29 @@ namespace Oqtane.Migrations.EntityBuilders
|
||||||
return table.Column<int>(name: RewriteName(name), nullable: nullable);
|
return table.Column<int>(name: RewriteName(name), nullable: nullable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddMaxStringColumn(string name, int length, bool nullable = false)
|
public void AddMaxStringColumn(string name, int length, bool nullable = false, bool unicode = true)
|
||||||
{
|
{
|
||||||
_migrationBuilder.AddColumn<string>(RewriteName(name), RewriteName(EntityTableName), nullable: nullable, unicode: true);
|
_migrationBuilder.AddColumn<string>(RewriteName(name), RewriteName(EntityTableName), nullable: nullable, unicode: unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected OperationBuilder<AddColumnOperation> AddMaxStringColumn(ColumnsBuilder table, string name, bool nullable = false)
|
protected OperationBuilder<AddColumnOperation> AddMaxStringColumn(ColumnsBuilder table, string name, bool nullable = false, bool unicode = true)
|
||||||
{
|
{
|
||||||
return table.Column<string>(name: RewriteName(name), nullable: nullable, unicode: true);
|
return table.Column<string>(name: RewriteName(name), nullable: nullable, unicode: unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddStringColumn(string name, int length, bool nullable = false)
|
public void AddStringColumn(string name, int length, bool nullable = false, bool unicode = true)
|
||||||
{
|
{
|
||||||
_migrationBuilder.AddColumn<string>(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: true);
|
_migrationBuilder.AddColumn<string>(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected OperationBuilder<AddColumnOperation> AddStringColumn(ColumnsBuilder table, string name, int length, bool nullable = false)
|
protected OperationBuilder<AddColumnOperation> AddStringColumn(ColumnsBuilder table, string name, int length, bool nullable = false, bool unicode = true)
|
||||||
{
|
{
|
||||||
return table.Column<string>(name: RewriteName(name), maxLength: length, nullable: nullable, unicode: true);
|
return table.Column<string>(name: RewriteName(name), maxLength: length, nullable: nullable, unicode: unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AlterStringColumn(string name, int length, bool nullable = false)
|
public void AlterStringColumn(string name, int length, bool nullable = false, bool unicode = true)
|
||||||
{
|
{
|
||||||
_migrationBuilder.AlterColumn<string>(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable);
|
_migrationBuilder.AlterColumn<string>(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DropColumn(string name)
|
public void DropColumn(string name)
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
<EmbeddedResource Include="Scripts\Tenant.02.00.01.01.sql" />
|
<EmbeddedResource Include="Scripts\Tenant.02.00.01.01.sql" />
|
||||||
<EmbeddedResource Include="Scripts\Tenant.02.00.01.02.sql" />
|
<EmbeddedResource Include="Scripts\Tenant.02.00.01.02.sql" />
|
||||||
<EmbeddedResource Include="Scripts\Tenant.02.00.01.03.sql" />
|
<EmbeddedResource Include="Scripts\Tenant.02.00.01.03.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\MigrateMaster.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.4" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.4" />
|
||||||
|
|
|
@ -7,8 +7,13 @@ namespace Oqtane.Repository
|
||||||
public interface ISqlRepository
|
public interface ISqlRepository
|
||||||
{
|
{
|
||||||
void ExecuteScript(Tenant tenant, string script);
|
void ExecuteScript(Tenant tenant, string script);
|
||||||
|
|
||||||
|
bool ExecuteScript(string connectionString, Assembly assembly, string filename);
|
||||||
|
|
||||||
bool ExecuteScript(Tenant tenant, Assembly assembly, string filename);
|
bool ExecuteScript(Tenant tenant, Assembly assembly, string filename);
|
||||||
|
|
||||||
int ExecuteNonQuery(Tenant tenant, string query);
|
int ExecuteNonQuery(Tenant tenant, string query);
|
||||||
|
|
||||||
SqlDataReader ExecuteReader(Tenant tenant, string query);
|
SqlDataReader ExecuteReader(Tenant tenant, string query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
// ReSharper disable ConvertToUsingDeclaration
|
||||||
|
// ReSharper disable InvertIf
|
||||||
|
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
|
@ -13,35 +16,41 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public void ExecuteScript(Tenant tenant, string script)
|
public void ExecuteScript(Tenant tenant, string script)
|
||||||
{
|
{
|
||||||
// execute script in curent tenant
|
// execute script in current tenant
|
||||||
foreach (string query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
foreach (var query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
ExecuteNonQuery(tenant, query);
|
ExecuteNonQuery(tenant, query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExecuteScript(Tenant tenant, Assembly assembly, string filename)
|
public bool ExecuteScript(string connectionString, Assembly assembly, string fileName)
|
||||||
{
|
{
|
||||||
// script must be included as an Embedded Resource within an assembly
|
var success = true;
|
||||||
bool success = true;
|
var script = GetScriptFromAssembly(assembly, fileName);
|
||||||
string script = "";
|
|
||||||
|
|
||||||
if (assembly != null)
|
if (!string.IsNullOrEmpty(script))
|
||||||
{
|
{
|
||||||
string name = assembly.GetManifestResourceNames().FirstOrDefault(item => item.EndsWith("." + filename));
|
try
|
||||||
if (name != null)
|
|
||||||
{
|
{
|
||||||
Stream resourceStream = assembly.GetManifestResourceStream(name);
|
foreach (var query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
||||||
if (resourceStream != null)
|
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(resourceStream))
|
ExecuteNonQuery(connectionString, query);
|
||||||
{
|
|
||||||
script = reader.ReadToEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExecuteScript(Tenant tenant, Assembly assembly, string fileName)
|
||||||
|
{
|
||||||
|
var success = true;
|
||||||
|
var script = GetScriptFromAssembly(assembly, fileName);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(script))
|
if (!string.IsNullOrEmpty(script))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -59,12 +68,26 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public int ExecuteNonQuery(Tenant tenant, string query)
|
public int ExecuteNonQuery(Tenant tenant, string query)
|
||||||
{
|
{
|
||||||
var conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
return ExecuteNonQuery(tenant.DBConnectionString, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlDataReader ExecuteReader(Tenant tenant, string query)
|
||||||
|
{
|
||||||
|
SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
||||||
|
SqlCommand cmd = conn.CreateCommand();
|
||||||
|
PrepareCommand(conn, cmd, query);
|
||||||
|
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
|
||||||
|
return dr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ExecuteNonQuery(string connectionString, string query)
|
||||||
|
{
|
||||||
|
var conn = new SqlConnection(FormatConnectionString(connectionString));
|
||||||
var cmd = conn.CreateCommand();
|
var cmd = conn.CreateCommand();
|
||||||
using (conn)
|
using (conn)
|
||||||
{
|
{
|
||||||
PrepareCommand(conn, cmd, query);
|
PrepareCommand(conn, cmd, query);
|
||||||
int val = -1;
|
var val = -1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
val = cmd.ExecuteNonQuery();
|
val = cmd.ExecuteNonQuery();
|
||||||
|
@ -77,13 +100,28 @@ namespace Oqtane.Repository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqlDataReader ExecuteReader(Tenant tenant, string query)
|
private string GetScriptFromAssembly(Assembly assembly, string fileName)
|
||||||
{
|
{
|
||||||
SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
// script must be included as an Embedded Resource within an assembly
|
||||||
SqlCommand cmd = conn.CreateCommand();
|
var script = "";
|
||||||
PrepareCommand(conn, cmd, query);
|
|
||||||
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
|
if (assembly != null)
|
||||||
return dr;
|
{
|
||||||
|
var name = assembly.GetManifestResourceNames().FirstOrDefault(item => item.EndsWith("." + fileName));
|
||||||
|
if (name != null)
|
||||||
|
{
|
||||||
|
var resourceStream = assembly.GetManifestResourceStream(name);
|
||||||
|
if (resourceStream != null)
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(resourceStream))
|
||||||
|
{
|
||||||
|
script = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PrepareCommand(SqlConnection conn, SqlCommand cmd, string query)
|
private void PrepareCommand(SqlConnection conn, SqlCommand cmd, string query)
|
||||||
|
|
17
Oqtane.Server/Scripts/MigrateMaster.sql
Normal file
17
Oqtane.Server/Scripts/MigrateMaster.sql
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.__EFMigrationsHistory') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE __EFMigrationsHistory
|
||||||
|
(
|
||||||
|
MigrationId nvarchar(150) NOT NULL CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY,
|
||||||
|
ProductVersion nvarchar(32) NOT NULL
|
||||||
|
)
|
||||||
|
END
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
VALUES ('Master.01.00.00.00', '5.0.0')
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
SELECT REPLACE(REPLACE(ScriptName, 'Oqtane.Scripts.', ''), '.sql', '') As MigrationId, ProductVersion = '5.0.0'
|
||||||
|
FROM SchemaVersions
|
||||||
|
WHERE ScriptName LIKE 'Oqtane.Scripts.Master.01%'
|
||||||
|
END
|
20
Oqtane.Server/Scripts/MigrateTenant.sql
Normal file
20
Oqtane.Server/Scripts/MigrateTenant.sql
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.__EFMigrationsHistory') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE __EFMigrationsHistory
|
||||||
|
(
|
||||||
|
MigrationId nvarchar(150) NOT NULL CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY,
|
||||||
|
ProductVersion nvarchar(32) NOT NULL
|
||||||
|
)
|
||||||
|
END
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
VALUES ('Tenant.01.00.00.00', '5.0.0')
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
SELECT REPLACE(REPLACE(ScriptName, 'Oqtane.Scripts.', ''), '.sql', '') As MigrationId, ProductVersion = '5.0.0'
|
||||||
|
FROM SchemaVersions
|
||||||
|
WHERE ScriptName LIKE 'Oqtane.Scripts.Tenant.01%'
|
||||||
|
OR ScriptName LIKE 'Oqtane.Scripts.Tenant.02%'
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
VALUES ('HtmlText.01.00.00.00', '5.0.0')
|
||||||
|
END
|
|
@ -5,8 +5,8 @@ namespace Oqtane.Shared {
|
||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
public const string PackageId = "Oqtane.Framework";
|
public const string PackageId = "Oqtane.Framework";
|
||||||
public const string Version = "2.0.1";
|
public const string Version = "2.1.0";
|
||||||
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1";
|
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0";
|
||||||
|
|
||||||
public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client";
|
public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client";
|
||||||
public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client";
|
public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user