Use DataMigration API to create tables by default

Created DataMigration class for the Settings module

--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-06-29 11:28:21 -07:00
parent a09536a44a
commit ca0de6aa49
16 changed files with 168 additions and 39 deletions

View File

@@ -14,6 +14,7 @@ using Orchard.Environment.Extensions.Folders;
using Orchard.Environment.Extensions.Models;
using Orchard.Tests.ContentManagement;
using Orchard.DataMigration;
using Orchard.Data.Providers;
namespace Orchard.Tests.DataMigration {
[TestFixture]
@@ -50,7 +51,9 @@ namespace Orchard.Tests.DataMigration {
_folders = new StubFolders();
builder.RegisterInstance(new ShellSettings { DataTablePrefix = "TEST_"});
builder.RegisterType<SqlServerDataServicesProvider>().As<IDataServicesProvider>();
builder.RegisterType<DataServicesProviderFactory>().As<IDataServicesProviderFactory>();
builder.RegisterType<NullInterpreter>().As<IDataMigrationInterpreter>();
builder.RegisterInstance(_folders).As<IExtensionFolders>();
builder.RegisterType<ExtensionManager>().As<IExtensionManager>();

View File

@@ -65,7 +65,7 @@ namespace Orchard.Tests.DataMigration {
.CreateIndex("IDX_XYZ", "NickName"))
.AlterTable("User", table => table
.DropIndex("IDX_XYZ"))
.DropForeignKey("Addresse", "User_Address")
.DropForeignKey("Address", "User_Address")
.DropTable("Address")
.ExecuteSql("drop database", statement => statement.ForProvider("SQLite"))
.ExecuteSql("DROP DATABASE", statement => statement.ForProvider("SQLServer"));

View File

@@ -159,6 +159,7 @@
<Compile Include="Scheduling\Services\ScheduledTaskManager.cs" />
<Compile Include="Scheduling\Services\ScheduledTaskExecutor.cs" />
<Compile Include="Scheduling\Models\Task.cs" />
<Compile Include="Settings\DataMigrations\SettingsDataMigration.cs" />
<Compile Include="Settings\ViewModels\SiteCulturesViewModel.cs" />
<Compile Include="Settings\Drivers\SiteSettingsDriver.cs" />
<Compile Include="Settings\Metadata\ContentDefinitionManager.cs" />

View File

@@ -0,0 +1,89 @@
using Orchard.DataMigration;
namespace Orchard.Core.Settings.DataMigrations {
public class SettingsDataMigration : DataMigrationImpl {
public override string Feature {
get { return "Settings"; }
}
public int Create() {
//CREATE TABLE Settings_ContentFieldDefinitionRecord (Id integer, Name TEXT, primary key (Id));
SchemaBuilder.CreateTable("Settings_ContentFieldDefinitionRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Name")
);
//CREATE TABLE Settings_ContentPartDefinitionRecord (Id integer, Name TEXT, Hidden INTEGER, Settings TEXT, primary key (Id));
SchemaBuilder.CreateTable("Settings_ContentPartDefinitionRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Name")
.Column<int>("Hidden")
.Column<string>("Settings")
);
//CREATE TABLE Settings_ContentPartFieldDefinitionRecord (Id integer, Name TEXT, Settings TEXT, ContentFieldDefinitionRecord_id INTEGER, INTEGER, primary key (Id));
SchemaBuilder.CreateTable("Settings_ContentPartFieldDefinitionRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Name")
.Column<string>("Settings")
.Column<int>("ContentFieldDefinitionRecord_id")
.Column<int>("ContentPartDefinitionRecord_Id")
);
//CREATE TABLE Settings_ContentTypeDefinitionRecord (Id integer, Name TEXT, DisplayName TEXT, Hidden INTEGER, Settings TEXT, primary key (Id));
SchemaBuilder.CreateTable("Settings_ContentTypeDefinitionRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Name")
.Column<string>("DisplayName")
.Column<int>("Hidden")
.Column<string>("Settings")
);
//CREATE TABLE Settings_ContentTypePartDefinitionRecord (Id integer, Settings TEXT, ContentPartDefinitionRecord_id INTEGER, ContentTypeDefinitionRecord_Id INTEGER, primary key (Id));
SchemaBuilder.CreateTable("Settings_ContentTypePartDefinitionRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Settings")
.Column<int>("ContentPartDefinitionRecord_id")
.Column<int>("ContentTypeDefinitionRecord_Id")
);
//CREATE TABLE Settings_ShellDescriptorRecord (Id integer, SerialNumber INTEGER, primary key (Id));
SchemaBuilder.CreateTable("Settings_ShellDescriptorRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<int>("SerialNumber")
);
//CREATE TABLE Settings_ShellFeatureRecord (Id integer, Name TEXT, ShellDescriptorRecord_id INTEGER, primary key (Id));
SchemaBuilder.CreateTable("Settings_ShellFeatureRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Name")
.Column<int>("ShellDescriptorRecord_id"));
//CREATE TABLE Settings_ShellFeatureStateRecord (Id integer, Name TEXT, InstallState TEXT, EnableState TEXT, ShellStateRecord_Id INTEGER, primary key (Id));
SchemaBuilder.CreateTable("Settings_ShellFeatureStateRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Name")
.Column<string>("InstallState")
.Column<string>("EnableState")
.Column<int>("ShellStateRecord_Id")
);
//CREATE TABLE Settings_ShellParameterRecord (Id integer, Component TEXT, Name TEXT, Value TEXT, ShellDescriptorRecord_id INTEGER, primary key (Id));
SchemaBuilder.CreateTable("Settings_ShellParameterRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Component")
.Column<string>("Name")
.Column<string>("Value")
.Column<int>("ShellDescriptorRecord_id")
);
//CREATE TABLE Settings_ShellStateRecord (Id integer, primary key (Id));
SchemaBuilder.CreateTable("Settings_ShellStateRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("Name")
);
return 0010;
}
}
}

View File

@@ -43,6 +43,7 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="NHibernate, Version=2.1.2.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.ComponentModel.DataAnnotations">

View File

@@ -8,6 +8,9 @@ using Orchard.Core.Common.Models;
using Orchard.Core.Navigation.Models;
using Orchard.Core.Settings.Models;
using Orchard.Data;
using Orchard.Data.Providers;
using Orchard.DataMigration.Interpreters;
using Orchard.DataMigration.Schema;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.ShellBuilders;
@@ -30,7 +33,6 @@ namespace Orchard.Setup.Services {
private readonly IShellContainerFactory _shellContainerFactory;
private readonly ICompositionStrategy _compositionStrategy;
private readonly IProcessingEngine _processingEngine;
private readonly IDataMigrationManager _dataMigrationManager;
public SetupService(
ShellSettings shellSettings,
@@ -39,15 +41,13 @@ namespace Orchard.Setup.Services {
IShellSettingsManager shellSettingsManager,
IShellContainerFactory shellContainerFactory,
ICompositionStrategy compositionStrategy,
IProcessingEngine processingEngine,
IDataMigrationManager dataMigrationManager) {
IProcessingEngine processingEngine) {
_shellSettings = shellSettings;
_orchardHost = orchardHost;
_shellSettingsManager = shellSettingsManager;
_shellContainerFactory = shellContainerFactory;
_compositionStrategy = compositionStrategy;
_processingEngine = processingEngine;
_dataMigrationManager = dataMigrationManager;
T = NullLocalizer.Instance;
}
@@ -105,7 +105,16 @@ namespace Orchard.Setup.Services {
// initialize database explicitly, and store shell descriptor
var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellToplogy);
using (var environment = new StandaloneEnvironment(bootstrapLifetimeScope)) {
_dataMigrationManager.Update(new [] { "Orchard.Framework", "Settings" });
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>() );
schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table
.Column<int>("Id", column => column.PrimaryKey())
.Column<string>("DataMigrationClass")
.Column<int>("Current"));
var dataMigrationManager = environment.Resolve<IDataMigrationManager>();
dataMigrationManager.Update("Settings");
environment.Resolve<IShellDescriptorManager>().UpdateShellDescriptor(
0,

View File

@@ -9,6 +9,8 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Data.Providers;
using Orchard.DataMigration;
using Orchard.DataMigration.Interpreters;
using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.Mvc;
@@ -50,6 +52,9 @@ namespace Orchard.Setup {
builder.RegisterType<SafeModeText>().As<IText>().InstancePerLifetimeScope();
builder.RegisterType<SafeModeSiteService>().As<ISiteService>().InstancePerLifetimeScope();
builder.RegisterType<DefaultDataMigrationInterpreter>().As<IDataMigrationInterpreter>().InstancePerLifetimeScope();
builder.RegisterType<DataMigrationManager>().As<IDataMigrationManager>().InstancePerLifetimeScope();
}

View File

@@ -1,4 +1,7 @@
using NHibernate;
using System;
using FluentNHibernate.Cfg;
using NHibernate;
using NHibernate.Cfg;
namespace Orchard.Data.Providers {
public interface IDataServicesProvider : ITransientDependency {

View File

@@ -10,5 +10,6 @@ namespace Orchard.Data.Providers {
var provider = factory.CreateProvider(sessionFactoryParameters);
return provider != null ? provider.BuildSessionFactory(sessionFactoryParameters) : null;
}
}
}

View File

@@ -13,6 +13,7 @@ using Orchard.Logging;
namespace Orchard.Data {
public interface ISessionFactoryHolder : ISingletonDependency {
ISessionFactory GetSessionFactory();
SessionFactoryParameters CreateSessionFactoryParameters(bool createDatabase, bool updateSchema);
void CreateDatabase();
void UpdateSchema();
}
@@ -67,7 +68,7 @@ namespace Orchard.Data {
public ISessionFactory GetSessionFactory() {
lock (this) {
if (_sessionFactory == null) {
_sessionFactory = BuildSessionFactory(false /*createDatabase*/, true /*updateSchema*/);
_sessionFactory = BuildSessionFactory(false /*createDatabase*/, false /*updateSchema*/);
}
}
return _sessionFactory;
@@ -76,24 +77,24 @@ namespace Orchard.Data {
private ISessionFactory BuildSessionFactory(bool createDatabase, bool updateSchema) {
Logger.Debug("Building session factory");
var sessionFactory = _dataServicesProviderFactory.BuildSessionFactory(CreateSessionFactoryParameters(createDatabase, updateSchema));
return sessionFactory;
}
public SessionFactoryParameters CreateSessionFactoryParameters(bool createDatabase, bool updateSchema) {
var shellPath = _appDataFolder.Combine("Sites", _shellSettings.Name);
_appDataFolder.CreateDirectory(shellPath);
var shellFolder = _appDataFolder.MapPath(shellPath);
var sessionFactory = _dataServicesProviderFactory.BuildSessionFactory(new SessionFactoryParameters {
return new SessionFactoryParameters {
Provider = _shellSettings.DataProvider,
DataFolder = shellFolder,
ConnectionString = _shellSettings.DataConnectionString,
CreateDatabase = createDatabase,
UpdateSchema = updateSchema,
RecordDescriptors = _shellBlueprint.Records,
});
return sessionFactory;
};
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Orchard.Data;
using Orchard.Data.Providers;
using Orchard.DataMigration.Interpreters;
using Orchard.DataMigration.Schema;
using Orchard.Environment.Extensions;
@@ -18,24 +19,18 @@ namespace Orchard.DataMigration {
public class DataMigrationManager : IDataMigrationManager {
private readonly IEnumerable<IDataMigration> _dataMigrations;
private readonly IRepository<DataMigrationRecord> _dataMigrationRepository;
private readonly IDataMigrationGenerator _dataMigrationGenerator;
private readonly IExtensionManager _extensionManager;
private readonly IDataMigrationInterpreter _interpreter;
private readonly ShellBlueprint _shellBlueprint;
public DataMigrationManager(
IEnumerable<IDataMigration> dataMigrations,
IRepository<DataMigrationRecord> dataMigrationRepository,
IDataMigrationGenerator dataMigrationGenerator,
IExtensionManager extensionManager,
IDataMigrationInterpreter interpreter,
ShellBlueprint shellBlueprint) {
IDataMigrationInterpreter interpreter) {
_dataMigrations = dataMigrations;
_dataMigrationRepository = dataMigrationRepository;
_dataMigrationGenerator = dataMigrationGenerator;
_extensionManager = extensionManager;
_interpreter = interpreter;
_shellBlueprint = shellBlueprint;
Logger = NullLogger.Instance;
}
@@ -84,6 +79,8 @@ namespace Orchard.DataMigration {
public void Update(string feature){
Logger.Information("Updating {0}", feature);
// proceed with dependent features first, whatever the module it's in
var dependencies = ShellStateCoordinator.OrderByDependencies(_extensionManager.AvailableExtensions()
.SelectMany(ext => ext.Features))
@@ -119,12 +116,6 @@ namespace Orchard.DataMigration {
if(createMethod != null) {
current = (int)createMethod.Invoke(migration, new object[0]);
}
else {
var commands = _dataMigrationGenerator.CreateCommands(_shellBlueprint.Records.Where(record => record.Feature.Descriptor.Name == feature));
foreach(var command in commands) {
_interpreter.Visit(command);
}
}
}
var lookupTable = CreateUpgradeLookupTable(migration);

View File

@@ -1,7 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using FluentNHibernate.Cfg;
using Orchard.Data.Providers;
using Orchard.DataMigration.Schema;
using Orchard.Environment.ShellBuilders.Models;
@@ -9,9 +7,6 @@ namespace Orchard.DataMigration {
public class DefaultDataMigrationGenerator : IDataMigrationGenerator {
public IEnumerable<ISchemaBuilderCommand> CreateCommands(IEnumerable<RecordBlueprint> records) {
// use FluentNhibernate generation for this module
var persistenceModel = AbstractDataServicesProvider.CreatePersistenceModel(records);
var configuration = Fluently.Configure().Mappings(m => m.AutoMappings.Add(persistenceModel));
return Enumerable.Empty<ISchemaBuilderCommand>();
}

View File

@@ -86,6 +86,18 @@ namespace Orchard.DataMigration.Interpreters {
Visit(builder, createColumn);
}
var primaryKeys = command.TableCommands.OfType<CreateColumnCommand>().Where(ccc => ccc.IsPrimaryKey).Select(ccc=>ccc.ColumnName);
if(primaryKeys.Any()) {
if ( appendComma ) {
builder.Append(", ");
}
builder.Append(_dialect.PrimaryKeyString)
.Append(" ( ")
.Append(String.Join(", ", primaryKeys.ToArray()))
.Append(" )");
}
builder.Append(" )");
_sqlStatements.Add(builder.ToString());
@@ -298,10 +310,6 @@ namespace Orchard.DataMigration.Interpreters {
if ( command.IsUnique && _dialect.SupportsUnique ) {
builder.Append(" unique");
}
if ( command.IsPrimaryKey ) {
builder.Append(Space).Append(_dialect.PrimaryKeyString);
}
}
private void RunPendingStatements() {

View File

@@ -18,6 +18,23 @@ namespace Orchard.DataMigration.Schema {
return this;
}
public CreateTableCommand Column<T>(string columnName, Action<CreateColumnCommand> 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;
default:
Enum.TryParse(System.Type.GetTypeCode(typeof (T)).ToString(), true, out dbType);
break;
}
return Column(columnName, dbType, column);
}
public CreateTableCommand ContentPartRecord() {
/// TODO: Call Column() with necessary information for content part records
return this;

View File

@@ -1,9 +1,11 @@
using System;
using Orchard.DataMigration.Interpreters;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.DataMigration.Schema {
public class SchemaBuilder {
private readonly IDataMigrationInterpreter _interpreter;
public SchemaBuilder(IDataMigrationInterpreter interpreter) {
_interpreter = interpreter;
}
@@ -15,6 +17,10 @@ namespace Orchard.DataMigration.Schema {
return this;
}
public SchemaBuilder CreateTable<TRecord>(Action<CreateTableCommand> table) {
return CreateTable(typeof (TRecord).FullName.Replace(".", "_"), table);
}
public SchemaBuilder AlterTable(string name, Action<AlterTableCommand> table) {
var alterTable = new AlterTableCommand(name);
table(alterTable);

View File

@@ -356,7 +356,6 @@
<Compile Include="ContentManagement\ViewModels\TemplateViewModel.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="DataMigration\AutomaticDataMigration.cs" />
<Compile Include="DataMigration\Interpreters\ICommandInterpreter.cs" />
<Compile Include="DataMigration\Interpreters\DefaultDataMigrationInterpreter.cs" />
<Compile Include="DataMigration\Interpreters\IDataMigrationInterpreter.cs" />