mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-01-19 17:51:45 +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 IEnumerable<string> EnabledFeatures { get; set; }
|
||||
public XDocument RecipeDocument { get; set; }
|
||||
public bool DropExistingTables { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,8 @@
|
||||
<Compile Include="Providers\ExportActions\BuildRecipeAction.cs" />
|
||||
<Compile Include="Models\ExportActionConfigurationContext.cs" />
|
||||
<Compile Include="Models\ImportActionConfigurationContext.cs" />
|
||||
<Compile Include="Services\DatabaseManager.cs" />
|
||||
<Compile Include="Services\IDatabaseManager.cs" />
|
||||
<Compile Include="ViewModels\RecipeExecutionStepViewModel.cs" />
|
||||
<Compile Include="Services\ISetupService.cs" />
|
||||
<Compile Include="Models\SetupContext.cs" />
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
||||
private readonly IEnumerable<IRecipeExecutionStep> _recipeExecutionSteps;
|
||||
private readonly IRecipeParser _recipeParser;
|
||||
private readonly IRecipeExecutor _recipeExecutor;
|
||||
private readonly IDatabaseManager _databaseManager;
|
||||
|
||||
public ExecuteRecipeAction(
|
||||
IOrchardServices orchardServices,
|
||||
@@ -31,7 +32,8 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
||||
IFeatureManager featureManager,
|
||||
IEnumerable<IRecipeExecutionStep> recipeExecutionSteps,
|
||||
IRecipeParser recipeParser,
|
||||
IRecipeExecutor recipeExecutor) {
|
||||
IRecipeExecutor recipeExecutor,
|
||||
IDatabaseManager databaseManager) {
|
||||
|
||||
_orchardServices = orchardServices;
|
||||
_setupService = setupService;
|
||||
@@ -40,6 +42,7 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
||||
_recipeExecutionSteps = recipeExecutionSteps;
|
||||
_recipeParser = recipeParser;
|
||||
_recipeExecutor = recipeExecutor;
|
||||
_databaseManager = databaseManager;
|
||||
}
|
||||
|
||||
public override string Name { get { return "ExecuteRecipe"; } }
|
||||
@@ -153,8 +156,11 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
||||
}
|
||||
|
||||
private string Setup(XDocument recipeDocument) {
|
||||
// Delete the tenant tables.
|
||||
DropTenantDatabaseTables();
|
||||
|
||||
// Setup.
|
||||
var setupContext = new SetupContext {
|
||||
DropExistingTables = true,
|
||||
RecipeDocument = recipeDocument,
|
||||
AdminPassword = SuperUserPassword,
|
||||
AdminUsername = _orchardServices.WorkContext.CurrentSite.SuperUser,
|
||||
@@ -164,6 +170,7 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
||||
SiteName = _orchardServices.WorkContext.CurrentSite.SiteName,
|
||||
EnabledFeatures = _featureManager.GetEnabledFeatures().Select(x => x.Id).ToArray()
|
||||
};
|
||||
|
||||
return _setupService.Setup(setupContext);
|
||||
}
|
||||
|
||||
@@ -184,5 +191,10 @@ namespace Orchard.ImportExport.Providers.ImportActions {
|
||||
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.
|
||||
using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) {
|
||||
|
||||
using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) {
|
||||
|
||||
// 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.
|
||||
// Workaround to avoid a Transaction issue with PostgreSQL.
|
||||
environment.Resolve<ITransactionManager>().RequireNew();
|
||||
|
||||
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
||||
schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table
|
||||
.Column<int>("Id", column => column.PrimaryKey().Identity())
|
||||
.Column<string>("DataMigrationClass")
|
||||
@@ -131,10 +113,7 @@ namespace Orchard.ImportExport.Services
|
||||
while ( _processingEngine.AreTasksPending() )
|
||||
_processingEngine.ExecuteNextTask();
|
||||
|
||||
// Creating 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.
|
||||
|
||||
// Create a standalone environment.
|
||||
// Must mark state as Running - otherwise standalone environment is created "for setup".
|
||||
shellSettings.State = TenantState.Running;
|
||||
using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
||||
@@ -193,19 +172,5 @@ namespace Orchard.ImportExport.Services
|
||||
|
||||
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 IRecipeStepQueue _recipeStepQueue;
|
||||
private readonly IRepository<RecipeStepResultRecord> _recipeStepResultRecordRepository;
|
||||
private readonly ISessionLocator _sessionLocator;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
|
||||
public RecipesStep(
|
||||
IRecipeHarvester recipeHarvester,
|
||||
IRecipeStepQueue recipeStepQueue,
|
||||
IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository,
|
||||
ISessionLocator sessionLocator,
|
||||
ITransactionManager transactionManager,
|
||||
RecipeExecutionLogger logger) : base(logger) {
|
||||
|
||||
_recipeHarvester = recipeHarvester;
|
||||
_recipeStepQueue = recipeStepQueue;
|
||||
_recipeStepResultRecordRepository = recipeStepResultRecordRepository;
|
||||
_sessionLocator = sessionLocator;
|
||||
_transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
public override string Name { get { return "Recipes"; } }
|
||||
@@ -38,7 +38,7 @@ namespace Orchard.Recipes.Providers.Executors {
|
||||
public override void Execute(RecipeExecutionContext context) {
|
||||
var recipeElements = context.RecipeStep.Step.Elements();
|
||||
var recipesDictionary = new Dictionary<string, IDictionary<string, Recipe>>();
|
||||
var session = _sessionLocator.For(typeof(RecipeStepResultRecord));
|
||||
var session = _transactionManager.GetSession();
|
||||
|
||||
foreach (var recipeElement in recipeElements) {
|
||||
var extensionId = recipeElement.Attr("ExtensionId");
|
||||
|
||||
Reference in New Issue
Block a user