mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Fixed dropping of database tables during site reset.
This fixes an issue where only a subset of the actual tables were being deleted due to a minimal shell context.
This commit is contained in:
@@ -11,6 +11,5 @@ namespace Orchard.ImportExport.Models {
|
|||||||
public string DatabaseTablePrefix { get; set; }
|
public string DatabaseTablePrefix { get; set; }
|
||||||
public IEnumerable<string> EnabledFeatures { get; set; }
|
public IEnumerable<string> EnabledFeatures { get; set; }
|
||||||
public XDocument RecipeDocument { get; set; }
|
public XDocument RecipeDocument { get; set; }
|
||||||
public bool DropExistingTables { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,6 +87,8 @@
|
|||||||
<Compile Include="Providers\ExportActions\BuildRecipeAction.cs" />
|
<Compile Include="Providers\ExportActions\BuildRecipeAction.cs" />
|
||||||
<Compile Include="Models\ExportActionConfigurationContext.cs" />
|
<Compile Include="Models\ExportActionConfigurationContext.cs" />
|
||||||
<Compile Include="Models\ImportActionConfigurationContext.cs" />
|
<Compile Include="Models\ImportActionConfigurationContext.cs" />
|
||||||
|
<Compile Include="Services\DatabaseManager.cs" />
|
||||||
|
<Compile Include="Services\IDatabaseManager.cs" />
|
||||||
<Compile Include="ViewModels\RecipeExecutionStepViewModel.cs" />
|
<Compile Include="ViewModels\RecipeExecutionStepViewModel.cs" />
|
||||||
<Compile Include="Services\ISetupService.cs" />
|
<Compile Include="Services\ISetupService.cs" />
|
||||||
<Compile Include="Models\SetupContext.cs" />
|
<Compile Include="Models\SetupContext.cs" />
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
|||||||
private readonly IEnumerable<IRecipeExecutionStep> _recipeExecutionSteps;
|
private readonly IEnumerable<IRecipeExecutionStep> _recipeExecutionSteps;
|
||||||
private readonly IRecipeParser _recipeParser;
|
private readonly IRecipeParser _recipeParser;
|
||||||
private readonly IRecipeExecutor _recipeExecutor;
|
private readonly IRecipeExecutor _recipeExecutor;
|
||||||
|
private readonly IDatabaseManager _databaseManager;
|
||||||
|
|
||||||
public ExecuteRecipeAction(
|
public ExecuteRecipeAction(
|
||||||
IOrchardServices orchardServices,
|
IOrchardServices orchardServices,
|
||||||
@@ -31,7 +32,8 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
|||||||
IFeatureManager featureManager,
|
IFeatureManager featureManager,
|
||||||
IEnumerable<IRecipeExecutionStep> recipeExecutionSteps,
|
IEnumerable<IRecipeExecutionStep> recipeExecutionSteps,
|
||||||
IRecipeParser recipeParser,
|
IRecipeParser recipeParser,
|
||||||
IRecipeExecutor recipeExecutor) {
|
IRecipeExecutor recipeExecutor,
|
||||||
|
IDatabaseManager databaseManager) {
|
||||||
|
|
||||||
_orchardServices = orchardServices;
|
_orchardServices = orchardServices;
|
||||||
_setupService = setupService;
|
_setupService = setupService;
|
||||||
@@ -40,6 +42,7 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
|||||||
_recipeExecutionSteps = recipeExecutionSteps;
|
_recipeExecutionSteps = recipeExecutionSteps;
|
||||||
_recipeParser = recipeParser;
|
_recipeParser = recipeParser;
|
||||||
_recipeExecutor = recipeExecutor;
|
_recipeExecutor = recipeExecutor;
|
||||||
|
_databaseManager = databaseManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name { get { return "ExecuteRecipe"; } }
|
public override string Name { get { return "ExecuteRecipe"; } }
|
||||||
@@ -153,8 +156,11 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string Setup(XDocument recipeDocument) {
|
private string Setup(XDocument recipeDocument) {
|
||||||
|
// Delete the tenant tables.
|
||||||
|
DropTenantDatabaseTables();
|
||||||
|
|
||||||
|
// Setup.
|
||||||
var setupContext = new SetupContext {
|
var setupContext = new SetupContext {
|
||||||
DropExistingTables = true,
|
|
||||||
RecipeDocument = recipeDocument,
|
RecipeDocument = recipeDocument,
|
||||||
AdminPassword = SuperUserPassword,
|
AdminPassword = SuperUserPassword,
|
||||||
AdminUsername = _orchardServices.WorkContext.CurrentSite.SuperUser,
|
AdminUsername = _orchardServices.WorkContext.CurrentSite.SuperUser,
|
||||||
@@ -164,6 +170,7 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
|||||||
SiteName = _orchardServices.WorkContext.CurrentSite.SiteName,
|
SiteName = _orchardServices.WorkContext.CurrentSite.SiteName,
|
||||||
EnabledFeatures = _featureManager.GetEnabledFeatures().Select(x => x.Id).ToArray()
|
EnabledFeatures = _featureManager.GetEnabledFeatures().Select(x => x.Id).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
return _setupService.Setup(setupContext);
|
return _setupService.Setup(setupContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,5 +191,10 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
|||||||
step.Step.UpdateStep(context);
|
step.Step.UpdateStep(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DropTenantDatabaseTables() {
|
||||||
|
_databaseManager.DropTenantDatabaseTables();
|
||||||
|
_orchardServices.TransactionManager.RequireNew();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Orchard.Data;
|
||||||
|
using Orchard.Data.Migration.Interpreters;
|
||||||
|
using Orchard.Data.Migration.Schema;
|
||||||
|
using Orchard.Logging;
|
||||||
|
|
||||||
|
namespace Orchard.ImportExport.Services {
|
||||||
|
public class DatabaseManager : Component, IDatabaseManager {
|
||||||
|
private readonly ISessionFactoryHolder _sessionFactoryHolder;
|
||||||
|
private readonly IDataMigrationInterpreter _dataMigrationInterpreter;
|
||||||
|
|
||||||
|
public DatabaseManager(
|
||||||
|
ISessionFactoryHolder sessionFactoryHolder,
|
||||||
|
IDataMigrationInterpreter dataMigrationInterpreter) {
|
||||||
|
|
||||||
|
_sessionFactoryHolder = sessionFactoryHolder;
|
||||||
|
_dataMigrationInterpreter = dataMigrationInterpreter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> GetTenantDatabaseTableNames() {
|
||||||
|
var configuration = _sessionFactoryHolder.GetConfiguration();
|
||||||
|
var result = configuration.ClassMappings.Select(x => x.Table.Name);
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropTenantDatabaseTables() {
|
||||||
|
var tableNames = GetTenantDatabaseTableNames();
|
||||||
|
var schemaBuilder = new SchemaBuilder(_dataMigrationInterpreter);
|
||||||
|
|
||||||
|
foreach (var tableName in tableNames) {
|
||||||
|
try {
|
||||||
|
schemaBuilder.DropTable(schemaBuilder.RemoveDataTablePrefix(tableName));
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Logger.Warning(ex, "Failed to drop table '{0}'.", tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Orchard.ImportExport.Services {
|
||||||
|
public interface IDatabaseManager {
|
||||||
|
IEnumerable<string> GetTenantDatabaseTableNames();
|
||||||
|
void DropTenantDatabaseTables();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -87,29 +87,11 @@ namespace Orchard.ImportExport.Services
|
|||||||
|
|
||||||
// Initialize database explicitly, and store shell descriptor.
|
// Initialize database explicitly, and store shell descriptor.
|
||||||
using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) {
|
using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) {
|
||||||
|
|
||||||
using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) {
|
using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) {
|
||||||
|
// Workaround to avoid a Transaction issue with PostgreSQL.
|
||||||
// Check if the database is already created (in case an exception occured in the second phase).
|
|
||||||
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
|
||||||
var installationPresent = true;
|
|
||||||
try {
|
|
||||||
var tablePrefix = String.IsNullOrEmpty(shellSettings.DataTablePrefix) ? "" : shellSettings.DataTablePrefix + "_";
|
|
||||||
schemaBuilder.ExecuteSql("SELECT * FROM " + tablePrefix + "Settings_ShellDescriptorRecord");
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
installationPresent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (installationPresent) {
|
|
||||||
if (context.DropExistingTables) {
|
|
||||||
DropTenantDatabaseTables(environment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a workaround to avoid the Transaction issue for PostgreSQL.
|
|
||||||
environment.Resolve<ITransactionManager>().RequireNew();
|
environment.Resolve<ITransactionManager>().RequireNew();
|
||||||
|
|
||||||
|
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
||||||
schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table
|
schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table
|
||||||
.Column<int>("Id", column => column.PrimaryKey().Identity())
|
.Column<int>("Id", column => column.PrimaryKey().Identity())
|
||||||
.Column<string>("DataMigrationClass")
|
.Column<string>("DataMigrationClass")
|
||||||
@@ -131,10 +113,7 @@ namespace Orchard.ImportExport.Services
|
|||||||
while ( _processingEngine.AreTasksPending() )
|
while ( _processingEngine.AreTasksPending() )
|
||||||
_processingEngine.ExecuteNextTask();
|
_processingEngine.ExecuteNextTask();
|
||||||
|
|
||||||
// Creating a standalone environment.
|
// Create a standalone environment.
|
||||||
// In theory this environment can be used to resolve any normal components by interface, and those
|
|
||||||
// components will exist entirely in isolation - no crossover between the safemode container currently in effect.
|
|
||||||
|
|
||||||
// Must mark state as Running - otherwise standalone environment is created "for setup".
|
// Must mark state as Running - otherwise standalone environment is created "for setup".
|
||||||
shellSettings.State = TenantState.Running;
|
shellSettings.State = TenantState.Running;
|
||||||
using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
||||||
@@ -193,19 +172,5 @@ namespace Orchard.ImportExport.Services
|
|||||||
|
|
||||||
return executionId;
|
return executionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DropTenantDatabaseTables(IWorkContextScope environment) {
|
|
||||||
var sessionFactoryHolder = environment.Resolve<ISessionFactoryHolder>();
|
|
||||||
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
|
||||||
var configuration = sessionFactoryHolder.GetConfiguration();
|
|
||||||
foreach (var mapping in configuration.ClassMappings) {
|
|
||||||
try {
|
|
||||||
schemaBuilder.DropTable(mapping.Table.Name);
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
Logger.Warning(ex, "Failed to drop table '{0}'.", mapping.Table.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,19 +13,19 @@ namespace Orchard.Recipes.Providers.Executors {
|
|||||||
private readonly IRecipeHarvester _recipeHarvester;
|
private readonly IRecipeHarvester _recipeHarvester;
|
||||||
private readonly IRecipeStepQueue _recipeStepQueue;
|
private readonly IRecipeStepQueue _recipeStepQueue;
|
||||||
private readonly IRepository<RecipeStepResultRecord> _recipeStepResultRecordRepository;
|
private readonly IRepository<RecipeStepResultRecord> _recipeStepResultRecordRepository;
|
||||||
private readonly ISessionLocator _sessionLocator;
|
private readonly ITransactionManager _transactionManager;
|
||||||
|
|
||||||
public RecipesStep(
|
public RecipesStep(
|
||||||
IRecipeHarvester recipeHarvester,
|
IRecipeHarvester recipeHarvester,
|
||||||
IRecipeStepQueue recipeStepQueue,
|
IRecipeStepQueue recipeStepQueue,
|
||||||
IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository,
|
IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository,
|
||||||
ISessionLocator sessionLocator,
|
ITransactionManager transactionManager,
|
||||||
RecipeExecutionLogger logger) : base(logger) {
|
RecipeExecutionLogger logger) : base(logger) {
|
||||||
|
|
||||||
_recipeHarvester = recipeHarvester;
|
_recipeHarvester = recipeHarvester;
|
||||||
_recipeStepQueue = recipeStepQueue;
|
_recipeStepQueue = recipeStepQueue;
|
||||||
_recipeStepResultRecordRepository = recipeStepResultRecordRepository;
|
_recipeStepResultRecordRepository = recipeStepResultRecordRepository;
|
||||||
_sessionLocator = sessionLocator;
|
_transactionManager = transactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name { get { return "Recipes"; } }
|
public override string Name { get { return "Recipes"; } }
|
||||||
@@ -38,7 +38,7 @@ namespace Orchard.Recipes.Providers.Executors {
|
|||||||
public override void Execute(RecipeExecutionContext context) {
|
public override void Execute(RecipeExecutionContext context) {
|
||||||
var recipeElements = context.RecipeStep.Step.Elements();
|
var recipeElements = context.RecipeStep.Step.Elements();
|
||||||
var recipesDictionary = new Dictionary<string, IDictionary<string, Recipe>>();
|
var recipesDictionary = new Dictionary<string, IDictionary<string, Recipe>>();
|
||||||
var session = _sessionLocator.For(typeof(RecipeStepResultRecord));
|
var session = _transactionManager.GetSession();
|
||||||
|
|
||||||
foreach (var recipeElement in recipeElements) {
|
foreach (var recipeElement in recipeElements) {
|
||||||
var extensionId = recipeElement.Attr("ExtensionId");
|
var extensionId = recipeElement.Attr("ExtensionId");
|
||||||
|
|||||||
Reference in New Issue
Block a user