diff --git a/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs b/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs index 18712a91a..76e3a8e8f 100644 --- a/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs +++ b/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs @@ -12,7 +12,7 @@ namespace Orchard.Specs.Hosting { class TraceEnabledBuilder : SQLiteDataServicesProvider { public TraceEnabledBuilder(string dataFolder, string connectionString) : base(dataFolder, connectionString) { } - protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { + public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { var config = (SQLiteConfiguration)base.GetPersistenceConfigurer(createDatabase); //config.ShowSql(); return config; diff --git a/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs b/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs index a841c1ef8..2d0368ac3 100644 --- a/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs +++ b/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs @@ -64,12 +64,12 @@ namespace Orchard.Tests.Data.Builders { var parameters = new SessionFactoryParameters { Provider = "SQLite", DataFolder = _tempDataFolder, - UpdateSchema = true, RecordDescriptors = recordDescriptors }; var sessionFactory = manager .CreateProvider(parameters) - .BuildSessionFactory(parameters); + .BuildConfiguration(parameters) + .BuildSessionFactory(); var session = sessionFactory.OpenSession(); @@ -102,12 +102,12 @@ namespace Orchard.Tests.Data.Builders { Provider = "SqlServer", DataFolder = _tempDataFolder, ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;", - UpdateSchema = true, RecordDescriptors = recordDescriptors, }; var sessionFactory = manager .CreateProvider(parameters) - .BuildSessionFactory(parameters); + .BuildConfiguration(parameters) + .BuildSessionFactory(); diff --git a/src/Orchard.Tests/DataMigration/DataMigrationTests.cs b/src/Orchard.Tests/DataMigration/DataMigrationTests.cs index d2f14709d..53b69a822 100644 --- a/src/Orchard.Tests/DataMigration/DataMigrationTests.cs +++ b/src/Orchard.Tests/DataMigration/DataMigrationTests.cs @@ -59,7 +59,6 @@ namespace Orchard.Tests.DataMigration { builder.RegisterInstance(_folders).As(); builder.RegisterType().As(); builder.RegisterType().As(); - builder.RegisterType().As(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); _session = _sessionFactory.OpenSession(); builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As(); diff --git a/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs b/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs index 2053bffc1..a0ee24ec7 100644 --- a/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs +++ b/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs @@ -1,5 +1,4 @@ using System.Data; -using System.Linq; using Autofac; using NHibernate; using NUnit.Framework; diff --git a/src/Orchard.Web/Core/Contents/AdminMenu.cs b/src/Orchard.Web/Core/Contents/AdminMenu.cs index 0851117cf..6eefc5d61 100644 --- a/src/Orchard.Web/Core/Contents/AdminMenu.cs +++ b/src/Orchard.Web/Core/Contents/AdminMenu.cs @@ -18,10 +18,10 @@ namespace Orchard.Core.Contents { public string MenuName { get { return "admin"; } } public void GetNavigation(NavigationBuilder builder) { - var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name); + //var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name); - builder.Add(T("Content"), "1", menu => { - menu.Add(T("Manage Content"), "1.2", item => item.Action("List", "Admin", new {area = "Orchard.ContentTypes"})); + //builder.Add(T("Content"), "1", menu => { + // menu.Add(T("Manage Content"), "1.2", item => item.Action("List", "Admin", new {area = "Orchard.ContentTypes"})); //foreach (var contentTypeDefinition in contentTypeDefinitions) { // var ci = _contentManager.New(contentTypeDefinition.Name); // var cim = _contentManager.GetItemMetadata(ci); @@ -29,7 +29,7 @@ namespace Orchard.Core.Contents { // if (createRouteValues.Any()) // menu.Add(T("Create New {0}", contentTypeDefinition.DisplayName), "1.3", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues)); //} - }); + //}); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs index 92029ca21..c3a7cb9b9 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs @@ -1,11 +1,16 @@ -using Orchard.UI.Navigation; +using Orchard.Localization; +using Orchard.UI.Navigation; namespace Orchard.DevTools { public class AdminMenu : INavigationProvider { public string MenuName { get { return "admin"; } } + public Localizer T { get; set; } public void GetNavigation(NavigationBuilder builder) { - + builder.Add(T("Site Configuration"), "11", + menu => menu + .Add(T("Developer Tools"), "10.0", item => item.Action("Index", "Home", new { area = "Orchard.DevTools" }) + )); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs index 8ef6923cb..6422474da 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs @@ -3,27 +3,72 @@ using System.IO; using System.Linq; using System.Web.Hosting; using Orchard.Commands; +using Orchard.Data.Migration.Generator; +using Orchard.DevTools.Services; using Orchard.Environment.Extensions; namespace Orchard.DevTools.Commands { [OrchardFeature("Scaffolding")] public class ScaffoldingCommands : DefaultOrchardCommandHandler { private readonly IExtensionManager _extensionManager; + private readonly ISchemaCommandGenerator _schemaCommandGenerator; - public ScaffoldingCommands(IExtensionManager extensionManager) { + public ScaffoldingCommands(IExtensionManager extensionManager, + ISchemaCommandGenerator schemaCommandGenerator) { _extensionManager = extensionManager; + _schemaCommandGenerator = schemaCommandGenerator; } [OrchardSwitch] public bool IncludeInSolution { get; set; } + [CommandHelp("scaffolding create datamigration \r\n\t" + "Create a new Data Migration class")] + [CommandName("scaffolding create datamigration")] + public void CreateDataMigration(string featureName) { + Context.Output.WriteLine(T("Creating Data Migration for {0}", featureName)); + + foreach ( var extension in _extensionManager.AvailableExtensions() ) { + if ( extension.ExtensionType == "Module" && extension.Features.Any(f => String.Equals(f.Name, featureName, StringComparison.OrdinalIgnoreCase)) ) { + string dataMigrationsPath = HostingEnvironment.MapPath("~/Modules/" + extension.Name + "/DataMigrations/"); + string dataMigrationPath = dataMigrationsPath + extension.DisplayName + "DataMigration.cs"; + string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard.DevTools/ScaffoldingTemplates/"); + if ( !Directory.Exists(dataMigrationsPath) ) { + Directory.CreateDirectory(dataMigrationsPath); + } + if ( File.Exists(dataMigrationPath) ) { + Context.Output.WriteLine(T("Data migration already exists in target Module {0}.", extension.Name)); + return; + } + + var commands = _schemaCommandGenerator.GetCreateFeatureCommands(featureName, false).ToList(); + + var stringWriter = new StringWriter(); + var interpreter = new ScaffoldingCommandInterpreter(stringWriter); + + foreach ( var command in commands ) { + interpreter.Visit(command); + stringWriter.WriteLine(); + } + + string dataMigrationText = File.ReadAllText(templatesPath + "DataMigration.txt"); + dataMigrationText = dataMigrationText.Replace("$$FeatureName$$", featureName); + dataMigrationText = dataMigrationText.Replace("$$ClassName$$", extension.DisplayName); + dataMigrationText = dataMigrationText.Replace("$$Commands$$", stringWriter.ToString()); + File.WriteAllText(dataMigrationPath, dataMigrationText); + Context.Output.WriteLine(T("Data migration created successfully in Module {0}", extension.DisplayName)); + return; + } + } + Context.Output.WriteLine(T("Creating data migration failed: target Feature {0} could not be found.", featureName)); + } + [CommandHelp("scaffolding create module [/IncludeInSolution:true|false]\r\n\t" + "Create a new Orchard module")] [CommandName("scaffolding create module")] [OrchardSwitches("IncludeInSolution")] public void CreateModule(string moduleName) { Context.Output.WriteLine(T("Creating Module {0}", moduleName)); - if (_extensionManager.AvailableExtensions().Any(extension => extension.ExtensionType == "Module" && String.Equals(moduleName, extension.DisplayName, StringComparison.OrdinalIgnoreCase))) { + if ( _extensionManager.AvailableExtensions().Any(extension => extension.ExtensionType == "Module" && String.Equals(moduleName, extension.DisplayName, StringComparison.OrdinalIgnoreCase)) ) { Context.Output.WriteLine(T("Creating Module {0} failed: a module of the same name already exists", moduleName)); return; } diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs new file mode 100644 index 000000000..e2488d413 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs @@ -0,0 +1,38 @@ +using System; +using System.Web.Mvc; +using Orchard.Data.Migration.Generator; +using Orchard.Localization; +using Orchard.Mvc.ViewModels; +using Orchard.UI.Notify; + +namespace Orchard.DevTools.Controllers { + [ValidateInput(false)] + public class DataMigrationController : Controller { + private readonly ISchemaCommandGenerator _schemaCommandGenerator; + + public DataMigrationController(ISchemaCommandGenerator schemaCommandGenerator, IOrchardServices orchardServices) { + _schemaCommandGenerator = schemaCommandGenerator; + Services = orchardServices; + } + + public IOrchardServices Services { get; set; } + public Localizer T { get; set; } + + public ActionResult Index() { + return View(new BaseViewModel()); + } + + public ActionResult UpdateDatabase() { + try { + + _schemaCommandGenerator.UpdateDatabase(); + Services.Notifier.Information(T("Database updated successfuly")); + } + catch (Exception ex) { + Services.Notifier.Error(T("An error occured while updating the database: {0}", ex.Message)); + } + + return RedirectToAction("Index"); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/HomeController.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/HomeController.cs index dff4fe782..f27e317f6 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/HomeController.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/HomeController.cs @@ -4,9 +4,11 @@ using Orchard.Localization; using Orchard.Mvc.ViewModels; using Orchard.Themes; using Orchard.UI.Notify; +using Orchard.UI.Admin; namespace Orchard.DevTools.Controllers { [Themed] + [Admin] public class HomeController : Controller { private readonly INotifier _notifier; diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj index d348d426b..073d0e9c7 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj @@ -73,6 +73,7 @@ + @@ -80,6 +81,8 @@ + + @@ -92,6 +95,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/DataMigration.txt b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/DataMigration.txt new file mode 100644 index 000000000..e671bd79a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/DataMigration.txt @@ -0,0 +1,13 @@ +using System.Data; +using Orchard.Data.Migration; + +namespace $$FeatureName$$.DataMigrations { + public class $$ClassName$$DataMigration : DataMigrationImpl { + + public int Create() { + $$Commands$$ + + return 0100; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Services/ScaffoldingCommandInterpreter.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Services/ScaffoldingCommandInterpreter.cs new file mode 100644 index 000000000..b68ee832f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Services/ScaffoldingCommandInterpreter.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Orchard.Data.Migration.Interpreters; +using Orchard.Data.Migration.Schema; + +namespace Orchard.DevTools.Services { + public class ScaffoldingCommandInterpreter : AbstractDataMigrationInterpreter { + private readonly TextWriter _output; + + public ScaffoldingCommandInterpreter(TextWriter output) { + _output = output; + } + + public override void Visit(CreateTableCommand command) { + _output.WriteLine("// Creating table {0}", command.Name); + _output.WriteLine("\t\t\tSchemaBuilder.CreateTable(\"{0}\", table => table", command.Name); + + foreach ( var createColumn in command.TableCommands.OfType() ) { + var type = createColumn.DbType.ToString(); + var field = createColumn.ColumnName; + var options = new List(); + + if ( createColumn.IsPrimaryKey ) { + options.Add(string.Format("WithLength({0})", createColumn.Length)); + } + + if ( createColumn.IsUnique ) { + options.Add("Unique()"); + } + + if ( createColumn.IsNotNull ) { + options.Add("NotNull()"); + } + + if ( createColumn.IsPrimaryKey ) { + options.Add("PrimaryKey()"); + } + + if ( createColumn.Length.HasValue ) { + options.Add(string.Format("WithLength({0})", createColumn.Length )); + } + + if ( createColumn.Precision > 0 ) { + options.Add(string.Format("WithPrecision({0})", createColumn.Precision)); + options.Add(string.Format("WithScale({0})", createColumn.Scale)); + } + + _output.WriteLine("\t\t\t\t.Column(\"{0}\", DbType.{1}{2})", field, type, options.Any() ? ", column => column." + string.Join(".", options) : string.Empty); + } + + _output.WriteLine("\t\t\t);"); + + } + + public override void Visit(AlterTableCommand command) { + _output.WriteLine("// Altering table {0}", command.Name); + } + + public override void Visit(DropTableCommand command) { + _output.WriteLine("// Dropping table {0}", command.Name); + _output.WriteLine("\t\t\tSchemaBuilder.DropTable(\"{0}\", command.Name);"); + } + + public override void Visit(SqlStatementCommand command) { + _output.WriteLine("// Executing sql statement\n\n {0}", command.Sql); + } + + public override void Visit(CreateForeignKeyCommand command) { + _output.WriteLine("// Creating foreign key {0}", command.Name); + } + + public override void Visit(DropForeignKeyCommand command) { + _output.WriteLine("// Dropping foreign key {0}", command.Name); + } + + } +} diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx new file mode 100644 index 000000000..7a5ba876d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx @@ -0,0 +1,5 @@ +<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage"%> +<%@ Import Namespace="Orchard.Mvc.ViewModels"%> +

<%: Html.TitleForPage(T("Data Migration").ToString()) %>

+

<%: Html.ActionLink(T("Update Database").ToString(), "UpdateDatabase", "DataMigration") %>

+ diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx b/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx index 5b1a2def6..3e7859f27 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx @@ -4,4 +4,4 @@

<%: Html.ActionLink(T("Contents").ToString(), "Index", "Content") %>

<%: Html.ActionLink(T("Metadata").ToString(), "Index", "Metadata") %>

<%: Html.ActionLink(T("Test Unauthorized Request").ToString(), "NotAuthorized", "Home")%>

- +

<%: Html.ActionLink(T("Data migration").ToString(), "Index", "DataMigration")%>

diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs index 0799cdb97..292546ab1 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Linq; using Orchard.Commands; using Orchard.ContentManagement; -using Orchard.Indexing; -using Orchard.Security; using Orchard.Tasks.Indexing; namespace Orchard.Indexing.Commands { diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs b/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs index c1c11bd9d..9cd38b71a 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs @@ -5,7 +5,6 @@ namespace Orchard.Indexing.DataMigrations { public class IndexingDataMigration : DataMigrationImpl { public int Create() { - SchemaBuilder.CreateTable("IndexingTaskRecord", table => table .Column("Id", column => column.PrimaryKey()) .Column("Action") diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 228a1ffce..c9edbd46a 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Web; using System.Web.Mvc; +using Orchard.Data.Migration; using Orchard.Localization; using Orchard.Modules.ViewModels; using Orchard.Mvc.Results; @@ -11,10 +12,12 @@ using Orchard.Utility.Extensions; namespace Orchard.Modules.Controllers { public class AdminController : Controller { private readonly IModuleService _moduleService; + private readonly IDataMigrationManager _dataMigrationManager; - public AdminController(IOrchardServices services, IModuleService moduleService) { + public AdminController(IOrchardServices services, IModuleService moduleService, IDataMigrationManager dataMigrationManager) { Services = services; _moduleService = moduleService; + _dataMigrationManager = dataMigrationManager; T = NullLocalizer.Instance; } @@ -68,7 +71,9 @@ namespace Orchard.Modules.Controllers { return new HttpUnauthorizedResult(); var features = _moduleService.GetAvailableFeatures().ToList(); - return View(new FeaturesViewModel {Features = features}); + var featuresThatNeedUpdate = _dataMigrationManager.GetFeaturesThatNeedUpdate(); + + return View(new FeaturesViewModel { Features = features, FeaturesThatNeedUpdate = featuresThatNeedUpdate }); } [HttpPost] @@ -96,5 +101,24 @@ namespace Orchard.Modules.Controllers { return RedirectToAction("Features"); } + + [HttpPost] + public ActionResult Update(string id, bool? force) { + if ( !Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to manage features")) ) + return new HttpUnauthorizedResult(); + + if ( string.IsNullOrEmpty(id) ) + return new NotFoundResult(); + + try { + _dataMigrationManager.Update(id); + Services.Notifier.Information(T("The feature {0} was updated succesfuly", id)); + } + catch(Exception ex) { + Services.Notifier.Error(T("An error occured while updating the feature {0}: {1}", id, ex.Message)); + } + + return RedirectToAction("Features"); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs b/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs index fc98504a8..028bd671c 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs @@ -4,5 +4,6 @@ using Orchard.Mvc.ViewModels; namespace Orchard.Modules.ViewModels { public class FeaturesViewModel : BaseViewModel { public IEnumerable Features { get; set; } + public IEnumerable FeaturesThatNeedUpdate { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx index 8c0184511..0b660d61c 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx @@ -29,7 +29,7 @@ //hmmm...I feel like I've done this before... var featureId = feature.Descriptor.Name.AsFeatureId(n => T(n)); var featureState = feature.IsEnabled ? "enabled" : "disabled"; - var featureClassName = string.Format("feature {0}", featureState); + var featureClassName = string.Format("feature {0}", featureState + (Model.FeaturesThatNeedUpdate.Contains(feature.Descriptor.Name) ? " update" : String.Empty)); if (feature == features.First()) featureClassName += " first"; if (feature == features.Last()) @@ -65,7 +65,15 @@ <%: Html.Hidden("force", true)%> <% } - } %> + } + if(Model.FeaturesThatNeedUpdate.Contains(feature.Descriptor.Name)){ + using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Update", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { %> + <%: Html.Hidden("id", feature.Descriptor.Name, new { id = "" })%> + <%: Html.Hidden("force", true)%> + <% + } + } + %> <% } %> diff --git a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css index 8aada2d0f..6c98fa853 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css +++ b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css @@ -110,6 +110,16 @@ top:.4em; } +a.update { + margin-left:.5em; +} +.features .update.feature { + background:#ecc; +} +.features.summary-view .update.feature { + border-color:#e77; +} + .cathedral { bottom:0; font-size:.8em; @@ -121,4 +131,4 @@ .cathedral a:visited, .cathedral form.inline.link button { color:#aeaeae; -} \ No newline at end of file +} diff --git a/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs b/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs index 745b2fffd..24e8e3c4b 100644 --- a/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs +++ b/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs @@ -1,24 +1,33 @@ using System; +using System.Linq; using Orchard.Commands; +using Orchard.Data.Migration.Generator; +using Orchard.Data.Migration.Interpreters; namespace Orchard.Data.Migration.Commands { public class DataMigrationCommands : DefaultOrchardCommandHandler { private readonly IDataMigrationManager _dataMigrationManager; + private readonly IDataMigrationInterpreter _dataMigrationInterpreter; + private readonly ISchemaCommandGenerator _schemaCommandGenerator; public DataMigrationCommands( - IDataMigrationManager dataMigrationManager) { + IDataMigrationManager dataMigrationManager, + IDataMigrationInterpreter dataMigrationInterpreter, + ISchemaCommandGenerator schemaCommandGenerator + ) { _dataMigrationManager = dataMigrationManager; + _dataMigrationInterpreter = dataMigrationInterpreter; + _schemaCommandGenerator = schemaCommandGenerator; } [OrchardSwitch] - public string Feature { get; set; } + public bool Drop { get; set; } [CommandName("upgrade database")] - [CommandHelp("upgrade database /Feature: \r\n\t" + "Upgrades or create the database tables for the named ")] - [OrchardSwitches("Feature")] - public string UpgradeDatabase() { + [CommandHelp("upgrade database \r\n\t" + "Upgrades or create the database tables for the ")] + public string UpgradeDatabase(string featureName) { try { - _dataMigrationManager.Update(Feature); + _dataMigrationManager.Update(featureName); } catch ( Exception ex ) { Context.Output.WriteLine(T("An error occured while upgrading the database: " + ex.Message)); @@ -27,5 +36,45 @@ namespace Orchard.Data.Migration.Commands { return "Database upgraded"; } + + [CommandName("update database")] + [CommandHelp("update database \r\n\t" + "Automatically updates the database schema for the enabled features")] + public string UpdateDatabase() { + try { + _schemaCommandGenerator.UpdateDatabase(); + } + catch ( Exception ex ) { + Context.Output.WriteLine(T("An error occured while updating the database: " + ex.Message)); + return "Update terminated."; + } + + return "Database updated"; + } + + [CommandName("create tables")] + [CommandHelp("create tables [/Drop:true|false] \r\n\t" + "Creates the database tables for the and optionaly drops them before if specified")] + [OrchardSwitches("Drop")] + public string CreateTables(string featureName) { + var stringInterpreter = new StringCommandInterpreter(Context.Output); + try { + var commands = _schemaCommandGenerator.GetCreateFeatureCommands(featureName, Drop).ToList(); + if ( commands.Any() ) { + + foreach (var command in commands) { + stringInterpreter.Visit(command); + _dataMigrationInterpreter.Visit(command); + } + } + else { + return "There are no tables to create for this feature."; + } + } + catch ( Exception ex ) { + Context.Output.WriteLine(T("An error occured while creating the tables: " + ex.Message)); + return "Tables creation terminated."; + } + + return "Tables created"; + } } } \ No newline at end of file diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 6c258680a..e4f7bf2c3 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -24,11 +24,13 @@ namespace Orchard.Data.Migration { IEnumerable dataMigrations, IRepository dataMigrationRepository, IExtensionManager extensionManager, - IDataMigrationInterpreter interpreter) { + IDataMigrationInterpreter interpreter + ) { _dataMigrations = dataMigrations; _dataMigrationRepository = dataMigrationRepository; _extensionManager = extensionManager; _interpreter = interpreter; + Logger = NullLogger.Instance; } @@ -93,7 +95,7 @@ namespace Orchard.Data.Migration { var migrations = GetDataMigrations(feature); - // apply update methods to each migration class for the module + // apply update methods to each migration class for the module)))) foreach ( var migration in migrations ) { // copy the objet for the Linq query var tempMigration = migration; @@ -149,7 +151,7 @@ namespace Orchard.Data.Migration { // apply update methods to each migration class for the module foreach (var migration in migrations) { - // copy the objet for the Linq query + // copy the object for the Linq query var tempMigration = migration; // get current version for this migration diff --git a/src/Orchard/Data/Migration/DefaultDataMigrationGenerator.cs b/src/Orchard/Data/Migration/DefaultDataMigrationGenerator.cs deleted file mode 100644 index 5aeaea29e..000000000 --- a/src/Orchard/Data/Migration/DefaultDataMigrationGenerator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Orchard.Data.Migration.Schema; -using Orchard.Environment.ShellBuilders.Models; - -namespace Orchard.Data.Migration { - public class DefaultDataMigrationGenerator : IDataMigrationGenerator { - public IEnumerable CreateCommands(IEnumerable records) { - - - return Enumerable.Empty(); - } - } -} diff --git a/src/Orchard/Data/Migration/Generator/ISchemaCommandGenerator.cs b/src/Orchard/Data/Migration/Generator/ISchemaCommandGenerator.cs new file mode 100644 index 000000000..acfda2eab --- /dev/null +++ b/src/Orchard/Data/Migration/Generator/ISchemaCommandGenerator.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using Orchard.Data.Migration.Schema; + +namespace Orchard.Data.Migration.Generator { + public interface ISchemaCommandGenerator : IDependency { + /// + /// Returns a set of instances to execute in order to create the tables requiered by the specified feature. + /// + /// The name of the feature from which the tables need to be created. + /// Whether to generate drop commands for the created tables. + IEnumerable GetCreateFeatureCommands(string feature, bool drop); + + /// + /// Automatically updates the tables in the database. + /// + void UpdateDatabase(); + + /// + /// Creates the tables in the database. + /// + void CreateDatabase(); + + } +} \ No newline at end of file diff --git a/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs new file mode 100644 index 000000000..51e1a6353 --- /dev/null +++ b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs @@ -0,0 +1,95 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using NHibernate.Cfg; +using NHibernate.Mapping; +using NHibernate.Tool.hbm2ddl; +using Orchard.Data.Migration.Schema; +using Orchard.Data.Providers; +using NHibernate.Dialect; + +namespace Orchard.Data.Migration.Generator { + public class SchemaCommandGenerator : ISchemaCommandGenerator { + private readonly IDataServicesProviderFactory _dataServicesProviderFactory; + private readonly ISessionFactoryHolder _sessionFactoryHolder; + + public SchemaCommandGenerator( + IDataServicesProviderFactory dataServicesProviderFactory, + ISessionFactoryHolder sessionFactoryHolder) { + _dataServicesProviderFactory = dataServicesProviderFactory; + _sessionFactoryHolder = sessionFactoryHolder; + } + + public IEnumerable GetCreateFeatureCommands(string feature, bool drop) { + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + + if (!parameters.RecordDescriptors.Any()) { + yield break; + } + + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + Dialect.GetDialect(configuration.Properties); + var mapping = configuration.BuildMapping(); + + // get the tables using reflection + var tablesField = typeof(Configuration).GetField("tables", BindingFlags.Instance | BindingFlags.NonPublic); + var tables = ((IDictionary) tablesField.GetValue(configuration)).Values; + + + foreach(var table in tables.Where(t => parameters.RecordDescriptors.Any(rd => rd.Feature.Descriptor.Name == feature && rd.TableName == t.Name))) { + if(drop) { + yield return new DropTableCommand(table.Name); + } + + var command = new CreateTableCommand(table.Name); + + foreach(var column in table.ColumnIterator) { + var table1 = table; + var column1 = column; + var sqlType = column1.GetSqlTypeCode(mapping); + command.Column(column.Name, sqlType.DbType, + action => { + if (table1.PrimaryKey.Columns.Any(c => c.Name == column1.Name)) { + action.PrimaryKey(); + } + + if (column1.IsLengthDefined()) { + action.WithLength(column1.Length); + } + + if (column1.IsPrecisionDefined()) { + action.WithPrecision((byte) column1.Precision); + action.WithScale((byte) column1.Scale); + } + if (column1.IsNullable) { + action.Nullable(); + } + + if ( column1.IsUnique ) { + action.Unique(); + } + + if(column1.DefaultValue != null) { + action.WithDefault(column1.DefaultValue); + } + }); + } + + yield return command; + } + } + + public void UpdateDatabase() { + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + new SchemaUpdate(configuration).Execute(false, true); + } + + public void CreateDatabase() { + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + new SchemaExport(configuration).Execute(false, true, false); + } + + } +} diff --git a/src/Orchard/Data/Migration/IDataMigrationGenerator.cs b/src/Orchard/Data/Migration/IDataMigrationGenerator.cs deleted file mode 100644 index 2ce898dfd..000000000 --- a/src/Orchard/Data/Migration/IDataMigrationGenerator.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using FluentNHibernate.Cfg; -using Orchard.Data.Migration.Schema; -using Orchard.Environment.ShellBuilders.Models; - -namespace Orchard.Data.Migration { - // Builds and runs the representative migration create calls - public interface IDataMigrationGenerator : IDependency { - IEnumerable CreateCommands(IEnumerable records); - } -} diff --git a/src/Orchard/Data/Migration/Interpreters/AbstractDataMigrationInterpreter.cs b/src/Orchard/Data/Migration/Interpreters/AbstractDataMigrationInterpreter.cs new file mode 100644 index 000000000..4cd6a9439 --- /dev/null +++ b/src/Orchard/Data/Migration/Interpreters/AbstractDataMigrationInterpreter.cs @@ -0,0 +1,41 @@ +using Orchard.Data.Migration.Schema; + +namespace Orchard.Data.Migration.Interpreters { + public abstract class AbstractDataMigrationInterpreter { + + public void Visit(ISchemaBuilderCommand command) { + var schemaCommand = command as SchemaCommand; + if (schemaCommand == null) { + return; + } + + switch ( schemaCommand.Type ) { + case SchemaCommandType.CreateTable: + Visit((CreateTableCommand)schemaCommand); + break; + case SchemaCommandType.AlterTable: + Visit((AlterTableCommand)schemaCommand); + break; + case SchemaCommandType.DropTable: + Visit((DropTableCommand)schemaCommand); + break; + case SchemaCommandType.SqlStatement: + Visit((SqlStatementCommand)schemaCommand); + break; + case SchemaCommandType.CreateForeignKey: + Visit((CreateForeignKeyCommand)schemaCommand); + break; + case SchemaCommandType.DropForeignKey: + Visit((DropForeignKeyCommand)schemaCommand); + break; + } + } + + public abstract void Visit(CreateTableCommand command); + public abstract void Visit(AlterTableCommand command); + public abstract void Visit(DropTableCommand command); + public abstract void Visit(SqlStatementCommand command); + public abstract void Visit(CreateForeignKeyCommand command); + public abstract void Visit(DropForeignKeyCommand command); + } +} diff --git a/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs b/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs index fb2db6ee3..c9313ca82 100644 --- a/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs +++ b/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs @@ -7,25 +7,40 @@ using NHibernate; using NHibernate.Dialect; using NHibernate.SqlTypes; using Orchard.Data.Migration.Schema; +using Orchard.Data.Providers; using Orchard.Environment.Configuration; using Orchard.Logging; namespace Orchard.Data.Migration.Interpreters { - public class DefaultDataMigrationInterpreter : IDataMigrationInterpreter { + public class DefaultDataMigrationInterpreter : AbstractDataMigrationInterpreter, IDataMigrationInterpreter { private readonly ShellSettings _shellSettings; private readonly IEnumerable _commandInterpreters; private readonly ISession _session; private readonly Dialect _dialect; private readonly List _sqlStatements; + private readonly IDataServicesProviderFactory _dataServicesProviderFactory; + private readonly ISessionFactoryHolder _sessionFactoryHolder; + private const char Space = ' ' ; - public DefaultDataMigrationInterpreter(ShellSettings shellSettings, ISessionLocator sessionLocator, IEnumerable commandInterpreters) { + public DefaultDataMigrationInterpreter( + ShellSettings shellSettings, + ISessionLocator sessionLocator, + IEnumerable commandInterpreters, + IDataServicesProviderFactory dataServicesProviderFactory, + ISessionFactoryHolder sessionFactoryHolder) { _shellSettings = shellSettings; _commandInterpreters = commandInterpreters; _session = sessionLocator.For(typeof(DefaultDataMigrationInterpreter)); _sqlStatements = new List(); - _dialect = _shellSettings.DataProvider == "SQLite" ? (Dialect) new SQLiteDialect() : new MsSql2008Dialect(); + _dataServicesProviderFactory = dataServicesProviderFactory; + _sessionFactoryHolder = sessionFactoryHolder; + Logger = NullLogger.Instance; + + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + _dialect = Dialect.GetDialect(configuration.Properties); } public ILogger Logger { get; set; } @@ -34,35 +49,7 @@ namespace Orchard.Data.Migration.Interpreters { get { return _sqlStatements; } } - public void Visit(ISchemaBuilderCommand command) { - var schemaCommand = command as SchemaCommand; - if (schemaCommand == null) { - return; - } - - switch ( schemaCommand.Type ) { - case SchemaCommandType.CreateTable: - Visit((CreateTableCommand)schemaCommand); - break; - case SchemaCommandType.AlterTable: - Visit((AlterTableCommand)schemaCommand); - break; - case SchemaCommandType.DropTable: - Visit((DropTableCommand)schemaCommand); - break; - case SchemaCommandType.SqlStatement: - Visit((SqlStatementCommand)schemaCommand); - break; - case SchemaCommandType.CreateForeignKey: - Visit((CreateForeignKeyCommand)schemaCommand); - break; - case SchemaCommandType.DropForeignKey: - Visit((DropForeignKeyCommand)schemaCommand); - break; - } - } - - public void Visit(CreateTableCommand command) { + public override void Visit(CreateTableCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; @@ -103,7 +90,7 @@ namespace Orchard.Data.Migration.Interpreters { RunPendingStatements(); } - public void Visit(DropTableCommand command) { + public override void Visit(DropTableCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } @@ -116,7 +103,7 @@ namespace Orchard.Data.Migration.Interpreters { RunPendingStatements(); } - public void Visit(AlterTableCommand command) { + public override void Visit(AlterTableCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } @@ -229,18 +216,21 @@ namespace Orchard.Data.Migration.Interpreters { _dialect.QuoteForColumnName(command.IndexName)); _sqlStatements.Add(builder.ToString()); } - public void Visit(SqlStatementCommand command) { - if (command.Providers.Count == 0 || command.Providers.Contains(_shellSettings.DataProvider) ) { - if (ExecuteCustomInterpreter(command)) { - return; - } - _sqlStatements.Add(command.Sql); - RunPendingStatements(); + public override void Visit(SqlStatementCommand command) { + if (command.Providers.Count != 0 && !command.Providers.Contains(_shellSettings.DataProvider)) { + return; } + + if (ExecuteCustomInterpreter(command)) { + return; + } + _sqlStatements.Add(command.Sql); + + RunPendingStatements(); } - public void Visit(CreateForeignKeyCommand command) { + public override void Visit(CreateForeignKeyCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } @@ -261,7 +251,7 @@ namespace Orchard.Data.Migration.Interpreters { RunPendingStatements(); } - public void Visit(DropForeignKeyCommand command) { + public override void Visit(DropForeignKeyCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } diff --git a/src/Orchard/Data/Migration/Interpreters/StringCommandInterpreter.cs b/src/Orchard/Data/Migration/Interpreters/StringCommandInterpreter.cs new file mode 100644 index 000000000..056b45ac6 --- /dev/null +++ b/src/Orchard/Data/Migration/Interpreters/StringCommandInterpreter.cs @@ -0,0 +1,36 @@ +using System.IO; +using Orchard.Data.Migration.Schema; + +namespace Orchard.Data.Migration.Interpreters { + public class StringCommandInterpreter : AbstractDataMigrationInterpreter { + private readonly TextWriter _output; + + public StringCommandInterpreter(TextWriter output) { + _output = output; + } + + public override void Visit(CreateTableCommand command) { + _output.WriteLine("Creating table {0}", command.Name); + } + + public override void Visit(AlterTableCommand command) { + _output.WriteLine("Altering table {0}", command.Name); + } + + public override void Visit(DropTableCommand command) { + _output.WriteLine("Dropping table {0}", command.Name); + } + + public override void Visit(SqlStatementCommand command) { + _output.WriteLine("Executing sql statement\n\n {0}", command.Sql); + } + + public override void Visit(CreateForeignKeyCommand command) { + _output.WriteLine("Creating foreign key {0}", command.Name); + } + + public override void Visit(DropForeignKeyCommand command) { + _output.WriteLine("Dropping foreign key {0}", command.Name); + } + } +} diff --git a/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs b/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs index 5c295e385..eefc48aa3 100644 --- a/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs +++ b/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs @@ -19,25 +19,7 @@ namespace Orchard.Data.Migration.Schema { } public CreateTableCommand Column(string columnName, Action column = null) { - var dbType = System.Data.DbType.Object; - switch(System.Type.GetTypeCode(typeof(T))) { - case TypeCode.String : - dbType = DbType.String; - break; - case TypeCode.Int32: - dbType = DbType.Int32; - break; - case TypeCode.DateTime: - dbType = DbType.DateTime; - break; - case TypeCode.Boolean: - dbType = DbType.Boolean; - break; - default: - Enum.TryParse(System.Type.GetTypeCode(typeof (T)).ToString(), true, out dbType); - break; - } - + var dbType = SchemaUtils.ToDbType(typeof (T)); return Column(columnName, dbType, column); } @@ -50,5 +32,7 @@ namespace Orchard.Data.Migration.Schema { /// TODO: Call Column() with necessary information for content part records return this; } + + } } diff --git a/src/Orchard/Data/Migration/Schema/SchemaUtils.cs b/src/Orchard/Data/Migration/Schema/SchemaUtils.cs new file mode 100644 index 000000000..71bd85c36 --- /dev/null +++ b/src/Orchard/Data/Migration/Schema/SchemaUtils.cs @@ -0,0 +1,30 @@ +using System; +using System.Data; + +namespace Orchard.Data.Migration.Schema { + public static class SchemaUtils { + public static DbType ToDbType(Type type) { + DbType dbType; + switch ( System.Type.GetTypeCode(type) ) { + case TypeCode.String: + dbType = DbType.String; + break; + case TypeCode.Int32: + dbType = DbType.Int32; + break; + case TypeCode.DateTime: + dbType = DbType.DateTime; + break; + case TypeCode.Boolean: + dbType = DbType.Boolean; + break; + default: + Enum.TryParse(Type.GetTypeCode(type).ToString(), true, out dbType); + break; + } + + return dbType; + } + + } +} diff --git a/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs b/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs index f32517e88..170308a65 100644 --- a/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs @@ -16,30 +16,16 @@ using Orchard.Environment.ShellBuilders.Models; namespace Orchard.Data.Providers { public abstract class AbstractDataServicesProvider : IDataServicesProvider { - protected abstract IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase); + public abstract IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase); - public ISessionFactory BuildSessionFactory(SessionFactoryParameters parameters) { + public Configuration BuildConfiguration(SessionFactoryParameters parameters) { var database = GetPersistenceConfigurer(parameters.CreateDatabase); var persistenceModel = CreatePersistenceModel(parameters.RecordDescriptors); - var sessionFactory = Fluently.Configure() + return Fluently.Configure() .Database(database) .Mappings(m => m.AutoMappings.Add(persistenceModel)) - .ExposeConfiguration(config => Initialization(parameters, config)) - .BuildSessionFactory(); - - return sessionFactory; - } - - private static void Initialization(SessionFactoryParameters parameters, Configuration configuration) { - if (parameters.CreateDatabase) { - var export = new SchemaExport(configuration); - export.Execute(false/*script*/, true/*export*/, false/*justDrop*/); - } - else if (parameters.UpdateSchema) { - var update = new SchemaUpdate(configuration); - update.Execute(false/*script*/, true /*doUpdate*/); - } + .BuildConfiguration(); } public static AutoPersistenceModel CreatePersistenceModel(IEnumerable recordDescriptors) { @@ -65,8 +51,5 @@ namespace Orchard.Data.Providers { public IEnumerable GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); } } - - - } } \ No newline at end of file diff --git a/src/Orchard/Data/Providers/IDataServicesProvider.cs b/src/Orchard/Data/Providers/IDataServicesProvider.cs index 19e5a3176..7c9c909a3 100644 --- a/src/Orchard/Data/Providers/IDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/IDataServicesProvider.cs @@ -1,10 +1,12 @@ using System; using FluentNHibernate.Cfg; +using FluentNHibernate.Cfg.Db; using NHibernate; using NHibernate.Cfg; namespace Orchard.Data.Providers { public interface IDataServicesProvider : ITransientDependency { - ISessionFactory BuildSessionFactory(SessionFactoryParameters sessionFactoryParameters); + Configuration BuildConfiguration(SessionFactoryParameters sessionFactoryParameters); + IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase); } } diff --git a/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs b/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs index dbc619391..634309cd7 100644 --- a/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs @@ -15,7 +15,7 @@ namespace Orchard.Data.Providers { get { return "SQLite"; } } - protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { + public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { var persistence = SQLiteConfiguration.Standard; if (string.IsNullOrEmpty(_connectionString)) { var dataFile = Path.Combine(_dataFolder, "Orchard.db"); diff --git a/src/Orchard/Data/Providers/SessionFactoryParameters.cs b/src/Orchard/Data/Providers/SessionFactoryParameters.cs index d7ca8855c..e607582e5 100644 --- a/src/Orchard/Data/Providers/SessionFactoryParameters.cs +++ b/src/Orchard/Data/Providers/SessionFactoryParameters.cs @@ -5,6 +5,5 @@ namespace Orchard.Data.Providers { public class SessionFactoryParameters : DataServiceParameters { public IEnumerable RecordDescriptors { get; set; } public bool CreateDatabase { get; set; } - public bool UpdateSchema { get; set; } } } diff --git a/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs b/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs index 34ee1e0a0..5d61f558d 100644 --- a/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs @@ -16,7 +16,7 @@ namespace Orchard.Data.Providers { get { return "SqlServer"; } } - protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { + public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { var persistence = MsSqlConfiguration.MsSql2008; if (string.IsNullOrEmpty(_connectionString)) { throw new NotImplementedException(); diff --git a/src/Orchard/Data/SessionFactoryHolder.cs b/src/Orchard/Data/SessionFactoryHolder.cs index f462050a1..c7a41d5cf 100644 --- a/src/Orchard/Data/SessionFactoryHolder.cs +++ b/src/Orchard/Data/SessionFactoryHolder.cs @@ -1,10 +1,6 @@ -using System; -using System.IO; -using NHibernate; +using NHibernate; using Orchard.Data.Providers; using Orchard.Environment.Configuration; -using Orchard.Environment.Descriptor; -using Orchard.Environment.Descriptor.Models; using Orchard.Environment.ShellBuilders.Models; using Orchard.FileSystems.AppData; using Orchard.Localization; @@ -13,8 +9,7 @@ using Orchard.Logging; namespace Orchard.Data { public interface ISessionFactoryHolder : ISingletonDependency { ISessionFactory GetSessionFactory(); - void CreateDatabase(); - void UpdateSchema(); + SessionFactoryParameters GetSessionFactoryParameters(); } public class SessionFactoryHolder : ISessionFactoryHolder { @@ -42,61 +37,41 @@ namespace Orchard.Data { public Localizer T { get; set; } public ILogger Logger { get; set; } - public void CreateDatabase() { - lock (this) { - if (_sessionFactory != null) { - Logger.Error("CreateSchema can not be called after a session factory was created"); - throw new OrchardCoreException(T("CreateSchema can not be called after a session factory was created")); - } - - _sessionFactory = BuildSessionFactory(true /*createDatabase*/, false /*updateSchema*/); - } - } - - public void UpdateSchema() { - lock (this) { - if (_sessionFactory != null) { - Logger.Error("UpdateSchema can not be called after a session factory was created"); - throw new OrchardCoreException(T("UpdateSchema can not be called after a session factory was created")); - } - - _sessionFactory = BuildSessionFactory(false /*createDatabase*/, true /*updateSchema*/); - } - } - public ISessionFactory GetSessionFactory() { lock (this) { if (_sessionFactory == null) { - _sessionFactory = BuildSessionFactory(false /*createDatabase*/, false /*updateSchema*/); + _sessionFactory = BuildSessionFactory(); } } return _sessionFactory; } - private ISessionFactory BuildSessionFactory(bool createDatabase, bool updateSchema) { + private ISessionFactory BuildSessionFactory() { Logger.Debug("Building session factory"); + var parameters = GetSessionFactoryParameters(); + + var sessionFactory = _dataServicesProviderFactory + .CreateProvider(parameters) + .BuildConfiguration(parameters) + .BuildSessionFactory(); + + return sessionFactory; + } + + public SessionFactoryParameters GetSessionFactoryParameters() { var shellPath = _appDataFolder.Combine("Sites", _shellSettings.Name); _appDataFolder.CreateDirectory(shellPath); var shellFolder = _appDataFolder.MapPath(shellPath); - var parameters = new SessionFactoryParameters { + return new SessionFactoryParameters { Provider = _shellSettings.DataProvider, DataFolder = shellFolder, ConnectionString = _shellSettings.DataConnectionString, - CreateDatabase = createDatabase, - UpdateSchema = updateSchema, RecordDescriptors = _shellBlueprint.Records, }; - - var sessionFactory = _dataServicesProviderFactory - .CreateProvider(parameters) - .BuildSessionFactory(parameters); - - return sessionFactory; } - } diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index a4a40d938..e9337076f 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -359,13 +359,18 @@ Code
+ + + + + @@ -379,8 +384,6 @@ - -