Data migration for developers

- NHibernate auto-update is explicitly run by the user (dev) through a DevTool Controller Action or Command
- Generate the create method from the nhib schema

--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-07-05 13:35:50 -07:00
parent 24eb381be3
commit d428ebc2f8
31 changed files with 556 additions and 171 deletions

View File

@@ -12,7 +12,7 @@ namespace Orchard.Specs.Hosting {
class TraceEnabledBuilder : SQLiteDataServicesProvider { class TraceEnabledBuilder : SQLiteDataServicesProvider {
public TraceEnabledBuilder(string dataFolder, string connectionString) : base(dataFolder, connectionString) { 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); var config = (SQLiteConfiguration)base.GetPersistenceConfigurer(createDatabase);
//config.ShowSql(); //config.ShowSql();
return config; return config;

View File

@@ -64,12 +64,12 @@ namespace Orchard.Tests.Data.Builders {
var parameters = new SessionFactoryParameters { var parameters = new SessionFactoryParameters {
Provider = "SQLite", Provider = "SQLite",
DataFolder = _tempDataFolder, DataFolder = _tempDataFolder,
UpdateSchema = true,
RecordDescriptors = recordDescriptors RecordDescriptors = recordDescriptors
}; };
var sessionFactory = manager var sessionFactory = manager
.CreateProvider(parameters) .CreateProvider(parameters)
.BuildSessionFactory(parameters); .BuildConfiguration(parameters)
.BuildSessionFactory();
var session = sessionFactory.OpenSession(); var session = sessionFactory.OpenSession();
@@ -102,12 +102,12 @@ namespace Orchard.Tests.Data.Builders {
Provider = "SqlServer", Provider = "SqlServer",
DataFolder = _tempDataFolder, DataFolder = _tempDataFolder,
ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;", ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;",
UpdateSchema = true,
RecordDescriptors = recordDescriptors, RecordDescriptors = recordDescriptors,
}; };
var sessionFactory = manager var sessionFactory = manager
.CreateProvider(parameters) .CreateProvider(parameters)
.BuildSessionFactory(parameters); .BuildConfiguration(parameters)
.BuildSessionFactory();

View File

@@ -59,7 +59,6 @@ namespace Orchard.Tests.DataMigration {
builder.RegisterInstance(_folders).As<IExtensionFolders>(); builder.RegisterInstance(_folders).As<IExtensionFolders>();
builder.RegisterType<ExtensionManager>().As<IExtensionManager>(); builder.RegisterType<ExtensionManager>().As<IExtensionManager>();
builder.RegisterType<DataMigrationManager>().As<IDataMigrationManager>(); builder.RegisterType<DataMigrationManager>().As<IDataMigrationManager>();
builder.RegisterType<DefaultDataMigrationGenerator>().As<IDataMigrationGenerator>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
_session = _sessionFactory.OpenSession(); _session = _sessionFactory.OpenSession();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>(); builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>();

View File

@@ -3,27 +3,80 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Web.Hosting; using System.Web.Hosting;
using Orchard.Commands; using Orchard.Commands;
using Orchard.Data.Migration;
using Orchard.Data.Migration.Generator;
using Orchard.Data.Migration.Interpreters;
using Orchard.DevTools.Services;
using Orchard.Environment.Extensions; using Orchard.Environment.Extensions;
namespace Orchard.DevTools.Commands { namespace Orchard.DevTools.Commands {
[OrchardFeature("Scaffolding")] [OrchardFeature("Scaffolding")]
public class ScaffoldingCommands : DefaultOrchardCommandHandler { public class ScaffoldingCommands : DefaultOrchardCommandHandler {
private readonly IExtensionManager _extensionManager; private readonly IExtensionManager _extensionManager;
private readonly IDataMigrationManager _dataMigrationManager;
private readonly IDataMigrationInterpreter _dataMigrationInterpreter;
private readonly ISchemaCommandGenerator _schemaCommandGenerator;
public ScaffoldingCommands(IExtensionManager extensionManager) { public ScaffoldingCommands(IExtensionManager extensionManager,
IDataMigrationManager dataMigrationManager,
IDataMigrationInterpreter dataMigrationInterpreter,
ISchemaCommandGenerator schemaCommandGenerator) {
_extensionManager = extensionManager; _extensionManager = extensionManager;
_dataMigrationManager = dataMigrationManager;
_dataMigrationInterpreter = dataMigrationInterpreter;
_schemaCommandGenerator = schemaCommandGenerator;
} }
[OrchardSwitch] [OrchardSwitch]
public bool IncludeInSolution { get; set; } public bool IncludeInSolution { get; set; }
[CommandHelp("scaffolding create datamigration <feature-name> \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 <module-name> [/IncludeInSolution:true|false]\r\n\t" + "Create a new Orchard module")] [CommandHelp("scaffolding create module <module-name> [/IncludeInSolution:true|false]\r\n\t" + "Create a new Orchard module")]
[CommandName("scaffolding create module")] [CommandName("scaffolding create module")]
[OrchardSwitches("IncludeInSolution")] [OrchardSwitches("IncludeInSolution")]
public void CreateModule(string moduleName) { public void CreateModule(string moduleName) {
Context.Output.WriteLine(T("Creating Module {0}", 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)); Context.Output.WriteLine(T("Creating Module {0} failed: a module of the same name already exists", moduleName));
return; return;
} }

View File

@@ -0,0 +1,23 @@
using System.Web.Mvc;
using Orchard.Data.Migration.Generator;
using Orchard.DevTools.ViewModels;
namespace Orchard.DevTools.Controllers {
[ValidateInput(false)]
public class DataMigrationController : Controller {
private readonly ISchemaCommandGenerator _schemaCommandGenerator;
public DataMigrationController(ISchemaCommandGenerator schemaCommandGenerator) {
_schemaCommandGenerator = schemaCommandGenerator;
}
public ActionResult Index() {
var model = new DataMigrationIndexViewModel ();
_schemaCommandGenerator.UpdateDatabase();
return View(model);
}
}
}

View File

@@ -73,6 +73,7 @@
<Compile Include="Commands\ProfilingCommands.cs" /> <Compile Include="Commands\ProfilingCommands.cs" />
<Compile Include="Commands\ScaffoldingCommands.cs" /> <Compile Include="Commands\ScaffoldingCommands.cs" />
<Compile Include="Controllers\ContentController.cs" /> <Compile Include="Controllers\ContentController.cs" />
<Compile Include="Controllers\DataMigrationController.cs" />
<Compile Include="Controllers\HomeController.cs" /> <Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\MetadataController.cs" /> <Compile Include="Controllers\MetadataController.cs" />
<Compile Include="Handlers\DebugLinkHandler.cs" /> <Compile Include="Handlers\DebugLinkHandler.cs" />
@@ -80,9 +81,12 @@
<Compile Include="Models\Simple.cs" /> <Compile Include="Models\Simple.cs" />
<Compile Include="Permissions.cs" /> <Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Content Include="ScaffoldingTemplates\DataMigration.txt" />
<Compile Include="Services\ScaffoldingCommandInterpreter.cs" />
<Compile Include="Settings\DevToolsSettings.cs" /> <Compile Include="Settings\DevToolsSettings.cs" />
<Compile Include="ViewModels\ContentIndexViewModel.cs" /> <Compile Include="ViewModels\ContentIndexViewModel.cs" />
<Compile Include="ViewModels\ContentDetailsViewModel.cs" /> <Compile Include="ViewModels\ContentDetailsViewModel.cs" />
<Compile Include="ViewModels\DataMigrationIndexViewModel.cs" />
<Compile Include="ViewModels\MetadataIndexViewModel.cs" /> <Compile Include="ViewModels\MetadataIndexViewModel.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -92,6 +96,7 @@
<Content Include="ScaffoldingTemplates\ModuleCsProj.txt" /> <Content Include="ScaffoldingTemplates\ModuleCsProj.txt" />
<Content Include="ScaffoldingTemplates\ModuleManifest.txt" /> <Content Include="ScaffoldingTemplates\ModuleManifest.txt" />
<Content Include="ScaffoldingTemplates\ModuleWebConfig.txt" /> <Content Include="ScaffoldingTemplates\ModuleWebConfig.txt" />
<Content Include="Views\DataMigration\Index.aspx" />
<Content Include="Views\DefinitionTemplates\DevToolsSettings.ascx" /> <Content Include="Views\DefinitionTemplates\DevToolsSettings.ascx" />
<Content Include="Views\Home\_RenderableAction.ascx" /> <Content Include="Views\Home\_RenderableAction.ascx" />
<Content Include="Views\Home\Simple.aspx" /> <Content Include="Views\Home\Simple.aspx" />

View File

@@ -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;
}
}
}

View File

@@ -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<CreateColumnCommand>() ) {
var type = createColumn.DbType.ToString();
var field = createColumn.ColumnName;
var options = new List<string>();
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);
}
}
}

View File

@@ -0,0 +1,6 @@
using Orchard.Mvc.ViewModels;
namespace Orchard.DevTools.ViewModels {
public class DataMigrationIndexViewModel : BaseViewModel {
}
}

View File

@@ -0,0 +1,9 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<Orchard.DevTools.ViewModels.DataMigrationIndexViewModel>" %>
<style title="text/css">
ul
{
margin-left: 12px;
}
</style>
<h1>Data Migration</h1>

View File

@@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Orchard.Commands; using Orchard.Commands;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.Indexing;
using Orchard.Security;
using Orchard.Tasks.Indexing; using Orchard.Tasks.Indexing;
namespace Orchard.Indexing.Commands { namespace Orchard.Indexing.Commands {

View File

@@ -5,7 +5,6 @@ namespace Orchard.Indexing.DataMigrations {
public class IndexingDataMigration : DataMigrationImpl { public class IndexingDataMigration : DataMigrationImpl {
public int Create() { public int Create() {
SchemaBuilder.CreateTable("IndexingTaskRecord", table => table SchemaBuilder.CreateTable("IndexingTaskRecord", table => table
.Column<int>("Id", column => column.PrimaryKey()) .Column<int>("Id", column => column.PrimaryKey())
.Column<int>("Action") .Column<int>("Action")

View File

@@ -64,7 +64,7 @@
<Compile Include="AdminMenu.cs" /> <Compile Include="AdminMenu.cs" />
<Compile Include="Commands\IndexingCommands.cs" /> <Compile Include="Commands\IndexingCommands.cs" />
<Compile Include="Controllers\AdminController.cs" /> <Compile Include="Controllers\AdminController.cs" />
<Compile Include="DataMigrations\IndexingDataMigration.cs" /> <Compile Include="DataMigrations\_IndexingDataMigration.cs" />
<Compile Include="Handlers\CreateIndexingTaskHandler.cs" /> <Compile Include="Handlers\CreateIndexingTaskHandler.cs" />
<Compile Include="Models\IndexingTask.cs" /> <Compile Include="Models\IndexingTask.cs" />
<Compile Include="Models\IndexingTaskRecord.cs" /> <Compile Include="Models\IndexingTaskRecord.cs" />

View File

@@ -1,24 +1,33 @@
using System; using System;
using System.Linq;
using Orchard.Commands; using Orchard.Commands;
using Orchard.Data.Migration.Generator;
using Orchard.Data.Migration.Interpreters;
namespace Orchard.Data.Migration.Commands { namespace Orchard.Data.Migration.Commands {
public class DataMigrationCommands : DefaultOrchardCommandHandler { public class DataMigrationCommands : DefaultOrchardCommandHandler {
private readonly IDataMigrationManager _dataMigrationManager; private readonly IDataMigrationManager _dataMigrationManager;
private readonly IDataMigrationInterpreter _dataMigrationInterpreter;
private readonly ISchemaCommandGenerator _schemaCommandGenerator;
public DataMigrationCommands( public DataMigrationCommands(
IDataMigrationManager dataMigrationManager) { IDataMigrationManager dataMigrationManager,
IDataMigrationInterpreter dataMigrationInterpreter,
ISchemaCommandGenerator schemaCommandGenerator
) {
_dataMigrationManager = dataMigrationManager; _dataMigrationManager = dataMigrationManager;
_dataMigrationInterpreter = dataMigrationInterpreter;
_schemaCommandGenerator = schemaCommandGenerator;
} }
[OrchardSwitch] [OrchardSwitch]
public string Feature { get; set; } public bool Drop { get; set; }
[CommandName("upgrade database")] [CommandName("upgrade database")]
[CommandHelp("upgrade database /Feature:<feature> \r\n\t" + "Upgrades or create the database tables for the named <feature>")] [CommandHelp("upgrade database <feature-name> \r\n\t" + "Upgrades or create the database tables for the <feature-name>")]
[OrchardSwitches("Feature")] public string UpgradeDatabase(string featureName) {
public string UpgradeDatabase() {
try { try {
_dataMigrationManager.Update(Feature); _dataMigrationManager.Update(featureName);
} }
catch ( Exception ex ) { catch ( Exception ex ) {
Context.Output.WriteLine(T("An error occured while upgrading the database: " + ex.Message)); 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"; 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 <feature-name> [/Drop:true|false] \r\n\t" + "Creates the database tables for the <feature-name> 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";
}
} }
} }

View File

@@ -3,10 +3,15 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using FluentNHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using Orchard.Data.Migration.Generator;
using Orchard.Data.Migration.Interpreters; using Orchard.Data.Migration.Interpreters;
using Orchard.Data.Migration.Records; using Orchard.Data.Migration.Records;
using Orchard.Data.Migration.Schema; using Orchard.Data.Migration.Schema;
using Orchard.Data.Providers;
using Orchard.Environment.Extensions; using Orchard.Environment.Extensions;
using Orchard.Environment.ShellBuilders.Models;
using Orchard.Environment.State; using Orchard.Environment.State;
using Orchard.Logging; using Orchard.Logging;
@@ -19,16 +24,21 @@ namespace Orchard.Data.Migration {
private readonly IRepository<DataMigrationRecord> _dataMigrationRepository; private readonly IRepository<DataMigrationRecord> _dataMigrationRepository;
private readonly IExtensionManager _extensionManager; private readonly IExtensionManager _extensionManager;
private readonly IDataMigrationInterpreter _interpreter; private readonly IDataMigrationInterpreter _interpreter;
private readonly ISchemaCommandGenerator _generator;
public DataMigrationManager( public DataMigrationManager(
IEnumerable<IDataMigration> dataMigrations, IEnumerable<IDataMigration> dataMigrations,
IRepository<DataMigrationRecord> dataMigrationRepository, IRepository<DataMigrationRecord> dataMigrationRepository,
IExtensionManager extensionManager, IExtensionManager extensionManager,
IDataMigrationInterpreter interpreter) { IDataMigrationInterpreter interpreter,
ISchemaCommandGenerator generator
) {
_dataMigrations = dataMigrations; _dataMigrations = dataMigrations;
_dataMigrationRepository = dataMigrationRepository; _dataMigrationRepository = dataMigrationRepository;
_extensionManager = extensionManager; _extensionManager = extensionManager;
_interpreter = interpreter; _interpreter = interpreter;
_generator = generator;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
} }
@@ -93,7 +103,7 @@ namespace Orchard.Data.Migration {
var migrations = GetDataMigrations(feature); 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 ) { foreach ( var migration in migrations ) {
// copy the objet for the Linq query // copy the objet for the Linq query
var tempMigration = migration; var tempMigration = migration;
@@ -149,7 +159,7 @@ namespace Orchard.Data.Migration {
// 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) { foreach (var migration in migrations) {
// copy the objet for the Linq query // copy the object for the Linq query
var tempMigration = migration; var tempMigration = migration;
// get current version for this migration // get current version for this migration

View File

@@ -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<ISchemaBuilderCommand> CreateCommands(IEnumerable<RecordBlueprint> records) {
return Enumerable.Empty<ISchemaBuilderCommand>();
}
}
}

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
using Orchard.Data.Migration.Schema;
namespace Orchard.Data.Migration.Generator {
public interface ISchemaCommandGenerator : IDependency {
/// <summary>
/// Returns a set of <see cref="SchemaCommand"/> instances to execute in order to create the tables requiered by the specified feature.
/// </summary>
/// <param name="feature">The name of the feature from which the tables need to be created.</param>
/// <param name="drop">Whether to generate drop commands for the created tables.</param>
IEnumerable<SchemaCommand> GetCreateFeatureCommands(string feature, bool drop);
/// <summary>
/// Automatically updates the tables in the database.
/// </summary>
void UpdateDatabase();
/// <summary>
/// Creates the tables in the database.
/// </summary>
void CreateDatabase();
}
}

View File

@@ -0,0 +1,97 @@
using System;
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;
using Orchard.Environment.Extensions;
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<SchemaCommand> GetCreateFeatureCommands(string feature, bool drop) {
var parameters = _sessionFactoryHolder.GetSessionFactoryParameters();
if (!parameters.RecordDescriptors.Any()) {
yield break;
}
var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters);
var dialect = 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<string, Table>) 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);
}
}
}

View File

@@ -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<ISchemaBuilderCommand> CreateCommands(IEnumerable<RecordBlueprint> records);
}
}

View File

@@ -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);
}
}

View File

@@ -7,25 +7,40 @@ using NHibernate;
using NHibernate.Dialect; using NHibernate.Dialect;
using NHibernate.SqlTypes; using NHibernate.SqlTypes;
using Orchard.Data.Migration.Schema; using Orchard.Data.Migration.Schema;
using Orchard.Data.Providers;
using Orchard.Environment.Configuration; using Orchard.Environment.Configuration;
using Orchard.Logging; using Orchard.Logging;
namespace Orchard.Data.Migration.Interpreters { namespace Orchard.Data.Migration.Interpreters {
public class DefaultDataMigrationInterpreter : IDataMigrationInterpreter { public class DefaultDataMigrationInterpreter : AbstractDataMigrationInterpreter, IDataMigrationInterpreter {
private readonly ShellSettings _shellSettings; private readonly ShellSettings _shellSettings;
private readonly IEnumerable<ICommandInterpreter> _commandInterpreters; private readonly IEnumerable<ICommandInterpreter> _commandInterpreters;
private readonly ISession _session; private readonly ISession _session;
private readonly Dialect _dialect; private readonly Dialect _dialect;
private readonly List<string> _sqlStatements; private readonly List<string> _sqlStatements;
private readonly IDataServicesProviderFactory _dataServicesProviderFactory;
private readonly ISessionFactoryHolder _sessionFactoryHolder;
private const char Space = ' ' ; private const char Space = ' ' ;
public DefaultDataMigrationInterpreter(ShellSettings shellSettings, ISessionLocator sessionLocator, IEnumerable<ICommandInterpreter> commandInterpreters) { public DefaultDataMigrationInterpreter(
ShellSettings shellSettings,
ISessionLocator sessionLocator,
IEnumerable<ICommandInterpreter> commandInterpreters,
IDataServicesProviderFactory dataServicesProviderFactory,
ISessionFactoryHolder sessionFactoryHolder) {
_shellSettings = shellSettings; _shellSettings = shellSettings;
_commandInterpreters = commandInterpreters; _commandInterpreters = commandInterpreters;
_session = sessionLocator.For(typeof(DefaultDataMigrationInterpreter)); _session = sessionLocator.For(typeof(DefaultDataMigrationInterpreter));
_sqlStatements = new List<string>(); _sqlStatements = new List<string>();
_dialect = _shellSettings.DataProvider == "SQLite" ? (Dialect) new SQLiteDialect() : new MsSql2008Dialect(); _dataServicesProviderFactory = dataServicesProviderFactory;
_sessionFactoryHolder = sessionFactoryHolder;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
var parameters = _sessionFactoryHolder.GetSessionFactoryParameters();
var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters);
_dialect = Dialect.GetDialect(configuration.Properties);
} }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
@@ -34,35 +49,7 @@ namespace Orchard.Data.Migration.Interpreters {
get { return _sqlStatements; } get { return _sqlStatements; }
} }
public void Visit(ISchemaBuilderCommand command) { public override void Visit(CreateTableCommand 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) {
if ( ExecuteCustomInterpreter(command) ) { if ( ExecuteCustomInterpreter(command) ) {
return; return;
@@ -103,7 +90,7 @@ namespace Orchard.Data.Migration.Interpreters {
RunPendingStatements(); RunPendingStatements();
} }
public void Visit(DropTableCommand command) { public override void Visit(DropTableCommand command) {
if ( ExecuteCustomInterpreter(command) ) { if ( ExecuteCustomInterpreter(command) ) {
return; return;
} }
@@ -116,7 +103,7 @@ namespace Orchard.Data.Migration.Interpreters {
RunPendingStatements(); RunPendingStatements();
} }
public void Visit(AlterTableCommand command) { public override void Visit(AlterTableCommand command) {
if ( ExecuteCustomInterpreter(command) ) { if ( ExecuteCustomInterpreter(command) ) {
return; return;
} }
@@ -229,18 +216,21 @@ namespace Orchard.Data.Migration.Interpreters {
_dialect.QuoteForColumnName(command.IndexName)); _dialect.QuoteForColumnName(command.IndexName));
_sqlStatements.Add(builder.ToString()); _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) ) { if ( ExecuteCustomInterpreter(command) ) {
return; return;
} }
@@ -261,7 +251,7 @@ namespace Orchard.Data.Migration.Interpreters {
RunPendingStatements(); RunPendingStatements();
} }
public void Visit(DropForeignKeyCommand command) { public override void Visit(DropForeignKeyCommand command) {
if ( ExecuteCustomInterpreter(command) ) { if ( ExecuteCustomInterpreter(command) ) {
return; return;
} }

View File

@@ -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);
}
}
}

View File

@@ -19,25 +19,7 @@ namespace Orchard.Data.Migration.Schema {
} }
public CreateTableCommand Column<T>(string columnName, Action<CreateColumnCommand> column = null) { public CreateTableCommand Column<T>(string columnName, Action<CreateColumnCommand> column = null) {
var dbType = System.Data.DbType.Object; var dbType = SchemaUtils.ToDbType(typeof (T));
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;
}
return Column(columnName, dbType, column); return Column(columnName, dbType, column);
} }
@@ -50,5 +32,7 @@ namespace Orchard.Data.Migration.Schema {
/// TODO: Call Column() with necessary information for content part records /// TODO: Call Column() with necessary information for content part records
return this; return this;
} }
} }
} }

View File

@@ -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;
}
}
}

View File

@@ -16,30 +16,16 @@ using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Data.Providers { namespace Orchard.Data.Providers {
public abstract class AbstractDataServicesProvider : IDataServicesProvider { 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 database = GetPersistenceConfigurer(parameters.CreateDatabase);
var persistenceModel = CreatePersistenceModel(parameters.RecordDescriptors); var persistenceModel = CreatePersistenceModel(parameters.RecordDescriptors);
var sessionFactory = Fluently.Configure() return Fluently.Configure()
.Database(database) .Database(database)
.Mappings(m => m.AutoMappings.Add(persistenceModel)) .Mappings(m => m.AutoMappings.Add(persistenceModel))
.ExposeConfiguration(config => Initialization(parameters, config)) .BuildConfiguration();
.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*/);
}
} }
public static AutoPersistenceModel CreatePersistenceModel(IEnumerable<RecordBlueprint> recordDescriptors) { public static AutoPersistenceModel CreatePersistenceModel(IEnumerable<RecordBlueprint> recordDescriptors) {
@@ -65,8 +51,5 @@ namespace Orchard.Data.Providers {
public IEnumerable<Type> GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); } public IEnumerable<Type> GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); }
} }
} }
} }

View File

@@ -1,10 +1,12 @@
using System; using System;
using FluentNHibernate.Cfg; using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate; using NHibernate;
using NHibernate.Cfg; using NHibernate.Cfg;
namespace Orchard.Data.Providers { namespace Orchard.Data.Providers {
public interface IDataServicesProvider : ITransientDependency { public interface IDataServicesProvider : ITransientDependency {
ISessionFactory BuildSessionFactory(SessionFactoryParameters sessionFactoryParameters); Configuration BuildConfiguration(SessionFactoryParameters sessionFactoryParameters);
IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase);
} }
} }

View File

@@ -15,7 +15,7 @@ namespace Orchard.Data.Providers {
get { return "SQLite"; } get { return "SQLite"; }
} }
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
var persistence = SQLiteConfiguration.Standard; var persistence = SQLiteConfiguration.Standard;
if (string.IsNullOrEmpty(_connectionString)) { if (string.IsNullOrEmpty(_connectionString)) {
var dataFile = Path.Combine(_dataFolder, "Orchard.db"); var dataFile = Path.Combine(_dataFolder, "Orchard.db");

View File

@@ -5,6 +5,5 @@ namespace Orchard.Data.Providers {
public class SessionFactoryParameters : DataServiceParameters { public class SessionFactoryParameters : DataServiceParameters {
public IEnumerable<RecordBlueprint> RecordDescriptors { get; set; } public IEnumerable<RecordBlueprint> RecordDescriptors { get; set; }
public bool CreateDatabase { get; set; } public bool CreateDatabase { get; set; }
public bool UpdateSchema { get; set; }
} }
} }

View File

@@ -16,7 +16,7 @@ namespace Orchard.Data.Providers {
get { return "SqlServer"; } get { return "SqlServer"; }
} }
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
var persistence = MsSqlConfiguration.MsSql2008; var persistence = MsSqlConfiguration.MsSql2008;
if (string.IsNullOrEmpty(_connectionString)) { if (string.IsNullOrEmpty(_connectionString)) {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@@ -13,8 +13,7 @@ using Orchard.Logging;
namespace Orchard.Data { namespace Orchard.Data {
public interface ISessionFactoryHolder : ISingletonDependency { public interface ISessionFactoryHolder : ISingletonDependency {
ISessionFactory GetSessionFactory(); ISessionFactory GetSessionFactory();
void CreateDatabase(); SessionFactoryParameters GetSessionFactoryParameters();
void UpdateSchema();
} }
public class SessionFactoryHolder : ISessionFactoryHolder { public class SessionFactoryHolder : ISessionFactoryHolder {
@@ -42,61 +41,41 @@ namespace Orchard.Data {
public Localizer T { get; set; } public Localizer T { get; set; }
public ILogger Logger { 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() { public ISessionFactory GetSessionFactory() {
lock (this) { lock (this) {
if (_sessionFactory == null) { if (_sessionFactory == null) {
_sessionFactory = BuildSessionFactory(false /*createDatabase*/, false /*updateSchema*/); _sessionFactory = BuildSessionFactory();
} }
} }
return _sessionFactory; return _sessionFactory;
} }
private ISessionFactory BuildSessionFactory(bool createDatabase, bool updateSchema) { private ISessionFactory BuildSessionFactory() {
Logger.Debug("Building session factory"); 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); var shellPath = _appDataFolder.Combine("Sites", _shellSettings.Name);
_appDataFolder.CreateDirectory(shellPath); _appDataFolder.CreateDirectory(shellPath);
var shellFolder = _appDataFolder.MapPath(shellPath); var shellFolder = _appDataFolder.MapPath(shellPath);
var parameters = new SessionFactoryParameters { return new SessionFactoryParameters {
Provider = _shellSettings.DataProvider, Provider = _shellSettings.DataProvider,
DataFolder = shellFolder, DataFolder = shellFolder,
ConnectionString = _shellSettings.DataConnectionString, ConnectionString = _shellSettings.DataConnectionString,
CreateDatabase = createDatabase,
UpdateSchema = updateSchema,
RecordDescriptors = _shellBlueprint.Records, RecordDescriptors = _shellBlueprint.Records,
}; };
var sessionFactory = _dataServicesProviderFactory
.CreateProvider(parameters)
.BuildSessionFactory(parameters);
return sessionFactory;
} }
} }

View File

@@ -359,13 +359,18 @@
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="ContentManagement\DataMigrations\FrameworkDataMigration.cs" /> <Compile Include="ContentManagement\DataMigrations\FrameworkDataMigration.cs" />
<Compile Include="Data\Migration\Generator\ISchemaCommandGenerator.cs" />
<Compile Include="Data\Migration\Interpreters\AbstractDataMigrationInterpreter.cs" />
<Compile Include="Data\Migration\Interpreters\ICommandInterpreter.cs" /> <Compile Include="Data\Migration\Interpreters\ICommandInterpreter.cs" />
<Compile Include="Data\Migration\Interpreters\DefaultDataMigrationInterpreter.cs" /> <Compile Include="Data\Migration\Interpreters\DefaultDataMigrationInterpreter.cs" />
<Compile Include="Data\Migration\Interpreters\IDataMigrationInterpreter.cs" /> <Compile Include="Data\Migration\Interpreters\IDataMigrationInterpreter.cs" />
<Compile Include="Data\Migration\Interpreters\SqLiteCommandInterpreter.cs" /> <Compile Include="Data\Migration\Interpreters\SqLiteCommandInterpreter.cs" />
<Compile Include="Data\Migration\Interpreters\StringCommandInterpreter.cs" />
<Compile Include="Data\Migration\Schema\AddColumnCommand.cs" /> <Compile Include="Data\Migration\Schema\AddColumnCommand.cs" />
<Compile Include="Data\Migration\Schema\ISchemaBuilderCommand.cs" /> <Compile Include="Data\Migration\Schema\ISchemaBuilderCommand.cs" />
<Compile Include="Data\Migration\Schema\IShellSettings.cs" /> <Compile Include="Data\Migration\Schema\IShellSettings.cs" />
<Compile Include="Data\Migration\Generator\SchemaCommandGenerator.cs" />
<Compile Include="Data\Migration\Schema\SchemaUtils.cs" />
<Compile Include="Data\Migration\Schema\SqlStatementCommand.cs" /> <Compile Include="Data\Migration\Schema\SqlStatementCommand.cs" />
<Compile Include="Data\Migration\Schema\CreateColumnCommand.cs" /> <Compile Include="Data\Migration\Schema\CreateColumnCommand.cs" />
<Compile Include="Data\Migration\Schema\CreateForeignKeyCommand.cs" /> <Compile Include="Data\Migration\Schema\CreateForeignKeyCommand.cs" />
@@ -379,8 +384,6 @@
<Compile Include="Data\Migration\Commands\DataMigrationCommands.cs" /> <Compile Include="Data\Migration\Commands\DataMigrationCommands.cs" />
<Compile Include="Data\Migration\Schema\SchemaBuilder.cs" /> <Compile Include="Data\Migration\Schema\SchemaBuilder.cs" />
<Compile Include="Data\Migration\DataMigrationCoordinator.cs" /> <Compile Include="Data\Migration\DataMigrationCoordinator.cs" />
<Compile Include="Data\Migration\DefaultDataMigrationGenerator.cs" />
<Compile Include="Data\Migration\IDataMigrationGenerator.cs" />
<Compile Include="Data\Migration\DataMigration.cs" /> <Compile Include="Data\Migration\DataMigration.cs" />
<Compile Include="Data\Migration\DataMigrationManager.cs" /> <Compile Include="Data\Migration\DataMigrationManager.cs" />
<Compile Include="Data\Migration\Records\DataMigrationRecord.cs" /> <Compile Include="Data\Migration\Records\DataMigrationRecord.cs" />