mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-03 12:03:51 +08:00
Merge
--HG-- branch : dev
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
using System.Data;
|
||||
using NUnit.Framework;
|
||||
using Orchard.DataMigration.Schema;
|
||||
|
||||
namespace Orchard.Tests.DataMigration {
|
||||
[TestFixture]
|
||||
public class DataMigrationCommandsTests {
|
||||
|
||||
[Test]
|
||||
public void AllMethodsShouldBeCalledSuccessfully() {
|
||||
var schemaBuilder = new SchemaBuilder("TEST_");
|
||||
|
||||
schemaBuilder
|
||||
.CreateTable("User", table => table
|
||||
.ContentPartRecord()
|
||||
.Column("Id", DbType.Int32, column => column.PrimaryKey())
|
||||
.Column("Firstname", DbType.String, column => column.Length(255))
|
||||
.Column("Lastname", DbType.String, column => column.Precision(0).Scale(1))
|
||||
.ForeignKey("User_Address", fk => fk.On("Id", "Address", "UserId")))
|
||||
.CreateTable("Address", table => table
|
||||
.VersionedContentPartRecord()
|
||||
.Column("City", DbType.String)
|
||||
.Column("ZIP", DbType.Int32, column => column.Unique())
|
||||
.Column("UserId", DbType.Int32, column => column.NotNull()))
|
||||
.AlterTable("User", table => table
|
||||
.AddColumn("Age", DbType.Int32)
|
||||
.AlterColumn("Lastname", column => column.Default("John"))
|
||||
.AlterColumn("Lastname", column => column.Rename("John"))
|
||||
.DropColumn("Lastname")
|
||||
.CreateIndex("IDX_XYZ", "NickName")
|
||||
.DropIndex("IDX_XYZ")
|
||||
.AddForeignKey("FKL", fk => fk.On("Id", "A", "Id").On("Id", "B", "Id") )
|
||||
.DropForeignKey("FKL"))
|
||||
.DropTable("Address")
|
||||
.ExecuteSql("DROP DATABASE", statement => statement.ForDialect("SQLite").ForDialect("MsSqlServer2008"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,9 @@ using NHibernate;
|
||||
using NUnit.Framework;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Folders;
|
||||
using Orchard.Environment.Extensions.Loaders;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Tests.ContentManagement;
|
||||
using Orchard.DataMigration;
|
||||
@@ -17,7 +17,6 @@ namespace Orchard.Tests.DataMigration {
|
||||
[TestFixture]
|
||||
public class DataMigrationTests {
|
||||
private IContainer _container;
|
||||
private IExtensionManager _manager;
|
||||
private StubFolders _folders;
|
||||
private IDataMigrationManager _dataMigrationManager;
|
||||
private IRepository<DataMigrationRecord> _repository;
|
||||
@@ -25,13 +24,8 @@ namespace Orchard.Tests.DataMigration {
|
||||
private ISessionFactory _sessionFactory;
|
||||
private ISession _session;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
Init(Enumerable.Empty<Type>());
|
||||
}
|
||||
|
||||
public void Init(IEnumerable<Type> dataMigrations) {
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void CreateDb() {
|
||||
var databaseFileName = System.IO.Path.GetTempFileName();
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(
|
||||
databaseFileName,
|
||||
@@ -39,9 +33,22 @@ namespace Orchard.Tests.DataMigration {
|
||||
typeof(ContentItemVersionRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentTypeRecord));
|
||||
}
|
||||
|
||||
public void InitDb() {
|
||||
foreach ( var record in _repository.Fetch(m => true) ) {
|
||||
_repository.Delete(record);
|
||||
}
|
||||
_repository.Flush();
|
||||
}
|
||||
|
||||
public void Init(IEnumerable<Type> dataMigrations) {
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
_folders = new StubFolders();
|
||||
|
||||
builder.RegisterInstance(new ShellSettings { DataTablePrefix = "TEST_"});
|
||||
|
||||
builder.RegisterInstance(_folders).As<IExtensionFolders>();
|
||||
builder.RegisterType<ExtensionManager>().As<IExtensionManager>();
|
||||
builder.RegisterType<DataMigrationManager>().As<IDataMigrationManager>();
|
||||
@@ -53,10 +60,11 @@ namespace Orchard.Tests.DataMigration {
|
||||
builder.RegisterType(type).As<IDataMigration>();
|
||||
}
|
||||
_container = builder.Build();
|
||||
_manager = _container.Resolve<IExtensionManager>();
|
||||
_container.Resolve<IExtensionManager>();
|
||||
_dataMigrationManager = _container.Resolve<IDataMigrationManager>();
|
||||
_repository = _container.Resolve<IRepository<DataMigrationRecord>>();
|
||||
|
||||
InitDb();
|
||||
}
|
||||
|
||||
public class StubFolders : IExtensionFolders {
|
||||
@@ -139,6 +147,7 @@ namespace Orchard.Tests.DataMigration {
|
||||
return 999;
|
||||
}
|
||||
}
|
||||
|
||||
public class DataMigrationDependenciesModule2 : IDataMigration {
|
||||
public string Feature {
|
||||
get { return "Feature2"; }
|
||||
@@ -149,9 +158,52 @@ namespace Orchard.Tests.DataMigration {
|
||||
}
|
||||
}
|
||||
|
||||
public class DataMigrationWithSchemaBuilder : DataMigrationImpl {
|
||||
public override string Feature {
|
||||
get { return "Feature1"; }
|
||||
}
|
||||
|
||||
public int Create() {
|
||||
Assert.That(SchemaBuilder, Is.Not.Null);
|
||||
Assert.That(SchemaBuilder.TablePrefix, Is.EqualTo("TEST_"));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public class DataMigrationFeatureNeedUpdate1 : IDataMigration {
|
||||
public string Feature {
|
||||
get { return "Feature1"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class DataMigrationFeatureNeedUpdate2 : IDataMigration {
|
||||
public string Feature {
|
||||
get { return "Feature2"; }
|
||||
}
|
||||
|
||||
public int Create() {
|
||||
return 999;
|
||||
}
|
||||
}
|
||||
|
||||
public class DataMigrationFeatureNeedUpdate3 : IDataMigration {
|
||||
public string Feature {
|
||||
get { return "Feature3"; }
|
||||
}
|
||||
|
||||
public int Create() {
|
||||
return 999;
|
||||
}
|
||||
|
||||
public int UpdateFrom42() {
|
||||
return 999;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DataMigrationShouldDoNothingIfNoDataMigrationIsProvidedForFeature() {
|
||||
Init(new Type[] {typeof (DataMigrationEmpty)});
|
||||
Init(new[] {typeof (DataMigrationEmpty)});
|
||||
|
||||
_folders.Manifests.Add("Module2", @"
|
||||
name: Module2
|
||||
@@ -162,13 +214,13 @@ features:
|
||||
Description: Feature
|
||||
");
|
||||
|
||||
_dataMigrationManager.Upgrade("Feature1");
|
||||
_dataMigrationManager.Update("Feature1");
|
||||
Assert.That(_repository.Table.Count(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DataMigrationShouldDoNothingIfNoUpgradeOrCreateMethodWasFound() {
|
||||
Init(new Type[] { typeof(DataMigration11) });
|
||||
Init(new[] { typeof(DataMigration11) });
|
||||
|
||||
_folders.Manifests.Add("Module1", @"
|
||||
name: Module1
|
||||
@@ -179,13 +231,13 @@ features:
|
||||
Description: Feature
|
||||
");
|
||||
|
||||
_dataMigrationManager.Upgrade("Feature1");
|
||||
_dataMigrationManager.Update("Feature1");
|
||||
Assert.That(_repository.Table.Count(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateShouldReturnVersionNumber() {
|
||||
Init(new Type[] { typeof(DataMigration11Create) });
|
||||
Init(new[] { typeof(DataMigration11Create) });
|
||||
|
||||
_folders.Manifests.Add("Module1", @"
|
||||
name: Module1
|
||||
@@ -196,7 +248,7 @@ features:
|
||||
Description: Feature
|
||||
");
|
||||
|
||||
_dataMigrationManager.Upgrade("Feature1");
|
||||
_dataMigrationManager.Update("Feature1");
|
||||
Assert.That(_repository.Table.Count(), Is.EqualTo(1));
|
||||
Assert.That(_repository.Table.First().Current, Is.EqualTo(999));
|
||||
Assert.That(_repository.Table.First().DataMigrationClass, Is.EqualTo("Orchard.Tests.DataMigration.DataMigrationTests+DataMigration11Create"));
|
||||
@@ -204,7 +256,7 @@ features:
|
||||
|
||||
[Test]
|
||||
public void CreateCanBeFollowedByUpdates() {
|
||||
Init(new Type[] {typeof (DataMigrationCreateCanBeFollowedByUpdates)});
|
||||
Init(new[] {typeof (DataMigrationCreateCanBeFollowedByUpdates)});
|
||||
|
||||
_folders.Manifests.Add("Module1", @"
|
||||
name: Module1
|
||||
@@ -215,14 +267,14 @@ features:
|
||||
Description: Feature
|
||||
");
|
||||
|
||||
_dataMigrationManager.Upgrade("Feature1");
|
||||
_dataMigrationManager.Update("Feature1");
|
||||
Assert.That(_repository.Table.Count(), Is.EqualTo(1));
|
||||
Assert.That(_repository.Table.First().Current, Is.EqualTo(666));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SameMigrationClassCanEvolve() {
|
||||
Init(new Type[] { typeof(DataMigrationSameMigrationClassCanEvolve) });
|
||||
Init(new[] { typeof(DataMigrationSameMigrationClassCanEvolve) });
|
||||
|
||||
_folders.Manifests.Add("Module1", @"
|
||||
name: Module1
|
||||
@@ -232,12 +284,12 @@ features:
|
||||
Feature1:
|
||||
Description: Feature
|
||||
");
|
||||
_repository.Create(new DataMigrationRecord() {
|
||||
_repository.Create(new DataMigrationRecord {
|
||||
Current = 42,
|
||||
DataMigrationClass = "Orchard.Tests.DataMigration.DataMigrationTests+DataMigrationSameMigrationClassCanEvolve"
|
||||
});
|
||||
|
||||
_dataMigrationManager.Upgrade("Feature1");
|
||||
_dataMigrationManager.Update("Feature1");
|
||||
Assert.That(_repository.Table.Count(), Is.EqualTo(1));
|
||||
Assert.That(_repository.Table.First().Current, Is.EqualTo(999));
|
||||
}
|
||||
@@ -245,7 +297,7 @@ features:
|
||||
[Test]
|
||||
public void DependenciesShouldBeUpgradedFirst() {
|
||||
|
||||
Init(new Type[] { typeof(DataMigrationDependenciesModule1), typeof(DataMigrationDependenciesModule2) });
|
||||
Init(new[] { typeof(DataMigrationDependenciesModule1), typeof(DataMigrationDependenciesModule2) });
|
||||
|
||||
_folders.Manifests.Add("Module1", @"
|
||||
name: Module1
|
||||
@@ -265,12 +317,77 @@ features:
|
||||
Feature2:
|
||||
Description: Feature
|
||||
");
|
||||
_dataMigrationManager.Upgrade("Feature1");
|
||||
_dataMigrationManager.Update("Feature1");
|
||||
Assert.That(_repository.Table.Count(), Is.EqualTo(2));
|
||||
Assert.That(_repository.Fetch(d => d.Current == 999).Count(), Is.EqualTo(2));
|
||||
Assert.That(_repository.Fetch(d => d.DataMigrationClass == "Orchard.Tests.DataMigration.DataMigrationTests+DataMigrationDependenciesModule1").Count(), Is.EqualTo(1));
|
||||
Assert.That(_repository.Fetch(d => d.DataMigrationClass == "Orchard.Tests.DataMigration.DataMigrationTests+DataMigrationDependenciesModule2").Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DataMigrationImplShouldGetASchemaBuilder() {
|
||||
Init(new[] { typeof(DataMigrationWithSchemaBuilder) });
|
||||
|
||||
_folders.Manifests.Add("Module1", @"
|
||||
name: Module1
|
||||
version: 0.1
|
||||
orchardversion: 1
|
||||
features:
|
||||
Feature1:
|
||||
Description: Feature
|
||||
");
|
||||
|
||||
_dataMigrationManager.Update("Feature1");
|
||||
Assert.That(_repository.Table.Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldDetectFeaturesThatNeedUpdates() {
|
||||
|
||||
Init(new[] { typeof(DataMigrationFeatureNeedUpdate1), typeof(DataMigrationFeatureNeedUpdate2), typeof(DataMigrationFeatureNeedUpdate3) });
|
||||
|
||||
_folders.Manifests.Add("Module1", @"
|
||||
name: Module1
|
||||
version: 0.1
|
||||
orchardversion: 1
|
||||
features:
|
||||
Feature1:
|
||||
Description: Feature
|
||||
Feature2:
|
||||
Description: Feature
|
||||
Feature3:
|
||||
Description: Feature
|
||||
Feature4:
|
||||
Description: Feature
|
||||
");
|
||||
|
||||
// even if there is a data migration class, as it is empty there should me no migration to do
|
||||
Assert.That(_dataMigrationManager.GetFeaturesThatNeedUpdate().Contains("Feature1"), Is.False);
|
||||
|
||||
// there is no available class for this feature
|
||||
Assert.That(_dataMigrationManager.GetFeaturesThatNeedUpdate().Contains("Feature4"), Is.False);
|
||||
|
||||
// there is a create method and no record in db, so let's create it
|
||||
Assert.That(_dataMigrationManager.GetFeaturesThatNeedUpdate().Contains("Feature2"), Is.True);
|
||||
|
||||
// there is an UpdateFrom42 method, so it should be fired if Current == 42
|
||||
|
||||
_repository.Create(new DataMigrationRecord {
|
||||
Current = 42,
|
||||
DataMigrationClass = "Orchard.Tests.DataMigration.DataMigrationTests+DataMigrationFeatureNeedUpdate3"
|
||||
});
|
||||
|
||||
Assert.That(_dataMigrationManager.GetFeaturesThatNeedUpdate().Contains("Feature3"), Is.True);
|
||||
|
||||
_repository.Delete(_repository.Fetch(m => m.Current == 42).First());
|
||||
_repository.Flush();
|
||||
|
||||
_repository.Create(new DataMigrationRecord {
|
||||
Current = 43,
|
||||
DataMigrationClass = "Orchard.Tests.DataMigration.DataMigrationTests+DataMigrationFeatureNeedUpdate3"
|
||||
});
|
||||
|
||||
Assert.That(_dataMigrationManager.GetFeaturesThatNeedUpdate().Contains("Feature3"), Is.False);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,6 +180,7 @@
|
||||
<Compile Include="ContentManagement\Records\GammaRecord.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="DataMigration\DataMigrationCommandsTests.cs" />
|
||||
<Compile Include="DataMigration\DataMigrationTests.cs" />
|
||||
<Compile Include="DataUtility.cs" />
|
||||
<Compile Include="Data\Builders\SessionFactoryBuilderTests.cs" />
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Common.Fields;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Common.Drivers {
|
||||
[UsedImplicitly]
|
||||
public class ItemReferenceContentFieldDriver : ContentFieldDriver<ItemReferenceContentField> {
|
||||
public IOrchardServices Services { get; set; }
|
||||
private const string TemplateName = "Fields/Common.ItemReferenceContentField";
|
||||
|
||||
public ItemReferenceContentFieldDriver(IOrchardServices services) {
|
||||
Services = services;
|
||||
}
|
||||
|
||||
protected override string Prefix {
|
||||
get { return "ItemReferenceContentField"; }
|
||||
}
|
||||
|
||||
protected override DriverResult Display(ItemReferenceContentField field, string displayType) {
|
||||
var model = new ItemReferenceContentFieldDisplayViewModel {
|
||||
Item = Services.ContentManager.Get(field.ContentItemReference.Id)
|
||||
};
|
||||
|
||||
return ContentFieldTemplate(model, TemplateName, Prefix);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ItemReferenceContentField field) {
|
||||
var model = BuildEditorViewModel(field);
|
||||
return ContentFieldTemplate(model, TemplateName, Prefix).Location("primary", "6");
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ItemReferenceContentField field, IUpdateModel updater) {
|
||||
var model = BuildEditorViewModel(field);
|
||||
updater.TryUpdateModel(model, Prefix, null, null);
|
||||
return ContentFieldTemplate(model, TemplateName, Prefix).Location("primary", "6");
|
||||
}
|
||||
|
||||
private ItemReferenceContentFieldEditorViewModel BuildEditorViewModel(ItemReferenceContentField field) {
|
||||
return new ItemReferenceContentFieldEditorViewModel {
|
||||
Item = Services.ContentManager.Get(field.ContentItemReference.Id)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Core.Common.Fields {
|
||||
public class ItemReferenceContentField : ContentField {
|
||||
public ContentItemRecord ContentItemReference { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
|
||||
namespace Orchard.Core.Common.Handlers {
|
||||
public class ItemReferenceContentFieldHandler : ContentFieldHandler {
|
||||
public ItemReferenceContentFieldHandler(IEnumerable<IContentFieldDriver> contentFieldDrivers) : base(contentFieldDrivers) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Common.ViewModels {
|
||||
public class ItemReferenceContentFieldDisplayViewModel {
|
||||
private ContentItem _item;
|
||||
|
||||
public ContentItem Item {
|
||||
get { return _item; }
|
||||
set { _item = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Common.ViewModels {
|
||||
public class ItemReferenceContentFieldEditorViewModel {
|
||||
private ContentItem _item;
|
||||
|
||||
public ContentItem Item {
|
||||
get { return _item; }
|
||||
set { _item = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ItemReferenceContentFieldDisplayViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Common.ViewModels"%>
|
||||
<%= Html.ItemDisplayLink(Model.Item) %>
|
||||
@@ -0,0 +1,3 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ItemReferenceContentFieldEditorViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Common.ViewModels"%>
|
||||
<%= Html.ItemEditLink(Model.Item) %>
|
||||
@@ -106,28 +106,97 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
return EditType(id);
|
||||
}
|
||||
|
||||
var contentTypeDefinitionParts = viewModel.Parts.Select(
|
||||
p => new ContentTypeDefinition.Part(
|
||||
new ContentPartDefinition(
|
||||
p.PartDefinition.Name,
|
||||
p.PartDefinition.Fields.Select(
|
||||
f => new ContentPartDefinition.Field(
|
||||
new ContentFieldDefinition(f.FieldDefinition.Name),
|
||||
f.Name,
|
||||
f.Settings
|
||||
)
|
||||
),
|
||||
p.PartDefinition.Settings
|
||||
),
|
||||
p.Settings
|
||||
)
|
||||
).ToList();
|
||||
|
||||
if (viewModel.Fields.Any()) {
|
||||
var implicitContentTypeDefinitionPart = new ContentTypeDefinition.Part(
|
||||
new ContentPartDefinition(
|
||||
viewModel.Name,
|
||||
viewModel.Fields.Select(
|
||||
f => new ContentPartDefinition.Field(
|
||||
new ContentFieldDefinition(f.FieldDefinition.Name),
|
||||
f.Name,
|
||||
f.Settings
|
||||
)
|
||||
),
|
||||
null
|
||||
),
|
||||
null
|
||||
);
|
||||
contentTypeDefinitionParts.Add(implicitContentTypeDefinitionPart);
|
||||
}
|
||||
|
||||
//todo: apply the changes along the lines of but definately not resembling
|
||||
// for now this _might_ just get a little messy ->
|
||||
_contentDefinitionService.AlterTypeDefinition(
|
||||
new ContentTypeDefinition(
|
||||
viewModel.Name,
|
||||
viewModel.DisplayName,
|
||||
viewModel.Parts.Select(
|
||||
p => new ContentTypeDefinition.Part(
|
||||
new ContentPartDefinition(
|
||||
p.PartDefinition.Name,
|
||||
p.PartDefinition.Fields.Select(
|
||||
f => new ContentPartDefinition.Field(
|
||||
new ContentFieldDefinition(f.FieldDefinition.Name),
|
||||
f.Name,
|
||||
f.Settings
|
||||
)
|
||||
),
|
||||
p.PartDefinition.Settings
|
||||
),
|
||||
p.Settings
|
||||
)
|
||||
),
|
||||
contentTypeDefinitionParts,
|
||||
viewModel.Settings
|
||||
)
|
||||
);
|
||||
// little == lot
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
public ActionResult EditPart(string id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a part.")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var contentPartDefinition = _contentDefinitionService.GetPartDefinition(id);
|
||||
|
||||
if (contentPartDefinition == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
return View(new EditPartViewModel(contentPartDefinition));
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("EditPart")]
|
||||
public ActionResult EditPartPOST(string id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a part.")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var contentPartDefinition = _contentDefinitionService.GetPartDefinition(id);
|
||||
|
||||
if (contentPartDefinition == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
var viewModel = new EditPartViewModel();
|
||||
TryUpdateModel(viewModel);
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
return EditPart(id);
|
||||
}
|
||||
|
||||
//todo: apply the changes along the lines of but definately not resembling
|
||||
// for now this _might_ just get a little messy ->
|
||||
_contentDefinitionService.AlterPartDefinition(
|
||||
new ContentPartDefinition(
|
||||
viewModel.Name,
|
||||
viewModel.Fields.Select(
|
||||
f => new ContentPartDefinition.Field(
|
||||
new ContentFieldDefinition(f.FieldDefinition.Name),
|
||||
f.Name,
|
||||
f.Settings
|
||||
)
|
||||
),
|
||||
viewModel.Settings
|
||||
)
|
||||
);
|
||||
|
||||
@@ -49,12 +49,33 @@ namespace Orchard.Core.Contents.Services {
|
||||
|
||||
public void AlterTypeDefinition(ContentTypeDefinition contentTypeDefinition) {
|
||||
_contentDefinitionManager.StoreTypeDefinition(contentTypeDefinition);
|
||||
|
||||
var implicitTypePart = contentTypeDefinition.Parts.SingleOrDefault(p => p.PartDefinition.Name == contentTypeDefinition.Name);
|
||||
if (implicitTypePart != null) {
|
||||
AlterPartDefinition(implicitTypePart.PartDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveTypeDefinition(string name) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ContentPartDefinition GetPartDefinition(string name) {
|
||||
return _contentDefinitionManager.GetPartDefinition(name);
|
||||
}
|
||||
|
||||
public void AddPartDefinition(ContentPartDefinition contentPartDefinition) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AlterPartDefinition(ContentPartDefinition contentPartDefinition) {
|
||||
_contentDefinitionManager.StorePartDefinition(contentPartDefinition);
|
||||
}
|
||||
|
||||
public void RemovePartDefinition(string name) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
//gratuitously stolen from the RoutableService
|
||||
private static string GenerateTypeName(string displayName) {
|
||||
if (string.IsNullOrWhiteSpace(displayName))
|
||||
|
||||
@@ -8,5 +8,10 @@ namespace Orchard.Core.Contents.Services {
|
||||
void AddTypeDefinition(ContentTypeDefinition contentTypeDefinition);
|
||||
void AlterTypeDefinition(ContentTypeDefinition contentTypeDefinition);
|
||||
void RemoveTypeDefinition(string name);
|
||||
|
||||
ContentPartDefinition GetPartDefinition(string name);
|
||||
void AddPartDefinition(ContentPartDefinition contentPartDefinition);
|
||||
void AlterPartDefinition(ContentPartDefinition contentPartDefinition);
|
||||
void RemovePartDefinition(string name);
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,44 @@
|
||||
}
|
||||
.manage.add-to-type {
|
||||
margin-top:-4em;
|
||||
}
|
||||
|
||||
.manage-part h3,
|
||||
.manage-field h3 {
|
||||
border-bottom:1px solid #EAEAEA;
|
||||
}
|
||||
.manage-part .manage,
|
||||
.manage-field .manage {
|
||||
font-size:1.4em;
|
||||
margin-top:-2.4em;
|
||||
}
|
||||
.manage-part .manage.minor {
|
||||
margin-top:-1.7em;
|
||||
}
|
||||
.manage-part label,
|
||||
.manage-field label {
|
||||
font-weight:normal;
|
||||
}
|
||||
|
||||
/* should pull this back into the base admin theme css, w/out the .manage-part of course */
|
||||
.manage-part dl {
|
||||
margin:0 0 1em;
|
||||
overflow:auto;
|
||||
padding:6px 0 0;
|
||||
}
|
||||
.manage-part dt {
|
||||
font-weight:bold;
|
||||
}
|
||||
.manage-part dl dl {
|
||||
font-size:1em;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
.manage-part dd dt {
|
||||
clear:left;
|
||||
float:left;
|
||||
}
|
||||
.manage-part dd dd {
|
||||
float:left;
|
||||
padding-left:.5em;
|
||||
}
|
||||
@@ -13,13 +13,27 @@ namespace Orchard.Core.Contents.ViewModels {
|
||||
Name = contentTypeDefinition.Name;
|
||||
DisplayName = contentTypeDefinition.DisplayName;
|
||||
Settings = contentTypeDefinition.Settings;
|
||||
Parts = contentTypeDefinition.Parts.Select(p => new EditTypePartViewModel(p));
|
||||
Fields = GetTypeFields(contentTypeDefinition);
|
||||
Parts = GetTypeParts(contentTypeDefinition);
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public SettingsDictionary Settings { get; set; }
|
||||
public IEnumerable<EditPartFieldViewModel> Fields { get; set; }
|
||||
public IEnumerable<EditTypePartViewModel> Parts { get; set; }
|
||||
|
||||
private IEnumerable<EditPartFieldViewModel> GetTypeFields(ContentTypeDefinition contentTypeDefinition) {
|
||||
var implicitTypePart = contentTypeDefinition.Parts.SingleOrDefault(p => p.PartDefinition.Name == Name);
|
||||
|
||||
return implicitTypePart == null
|
||||
? Enumerable.Empty<EditPartFieldViewModel>()
|
||||
: implicitTypePart.PartDefinition.Fields.Select(f => new EditPartFieldViewModel(f));
|
||||
}
|
||||
|
||||
private IEnumerable<EditTypePartViewModel> GetTypeParts(ContentTypeDefinition contentTypeDefinition) {
|
||||
return contentTypeDefinition.Parts.Where(p => p.PartDefinition.Name != Name).Select(p => new EditTypePartViewModel(p));
|
||||
}
|
||||
}
|
||||
|
||||
public class EditTypePartViewModel {
|
||||
@@ -35,7 +49,7 @@ namespace Orchard.Core.Contents.ViewModels {
|
||||
public SettingsDictionary Settings { get; set; }
|
||||
}
|
||||
|
||||
public class EditPartViewModel {
|
||||
public class EditPartViewModel : BaseViewModel {
|
||||
public EditPartViewModel() {
|
||||
Fields = new List<EditPartFieldViewModel>();
|
||||
Settings = new SettingsDictionary();
|
||||
@@ -69,7 +83,7 @@ namespace Orchard.Core.Contents.ViewModels {
|
||||
public class EditFieldViewModel {
|
||||
public EditFieldViewModel() { }
|
||||
public EditFieldViewModel(ContentFieldDefinition contentFieldDefinition) {
|
||||
Name = Name;
|
||||
Name = contentFieldDefinition.Name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
19
src/Orchard.Web/Core/Contents/Views/Admin/EditPart.ascx
Normal file
19
src/Orchard.Web/Core/Contents/Views/Admin/EditPart.ascx
Normal file
@@ -0,0 +1,19 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<EditPartViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><%
|
||||
Html.RegisterStyle("admin.css"); %>
|
||||
<h1><%:Html.TitleForPage(T("Edit Part").ToString())%></h1><%
|
||||
using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<%:Html.ValidationSummary() %>
|
||||
<fieldset>
|
||||
<label for="Name"><%:T("Name") %></label>
|
||||
<%--// has unintended consequences (renamging the part) - changing the name creates a new part of that name--%>
|
||||
<%:Html.TextBoxFor(m => m.Name, new {@class = "textMedium"}) %>
|
||||
</fieldset>
|
||||
<%:Html.EditorFor(m => m.Settings, "Settings", "")%>
|
||||
<h2><%:T("Fields") %></h2>
|
||||
<div class="manage add-to-type"><%: Html.ActionLink(T("Add").Text, "AddField", new { }, new { @class = "button" })%></div>
|
||||
<%:Html.EditorFor(m => m.Fields, "Fields", "") %>
|
||||
<fieldset>
|
||||
<button class="primaryAction" type="submit"><%:T("Save") %></button>
|
||||
</fieldset><%
|
||||
} %>
|
||||
@@ -7,8 +7,10 @@ using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<fieldset>
|
||||
<label for="DisplayName"><%:T("Display Name") %></label>
|
||||
<%:Html.TextBoxFor(m => m.DisplayName, new {@class = "textMedium"}) %>
|
||||
<%--// has unintended consequences (renamging the type) - changing the name creates a new type of that name--%>
|
||||
<label for="Name"><%:T("Name") %></label>
|
||||
<%:Html.TextBoxFor(m => m.Name, new {@class = "textMedium"}) %>
|
||||
<%:Html.TextBoxFor(m => m.Name, new {@class = "textMedium", disabled = "disabled"}) %>
|
||||
<%:Html.HiddenFor(m => m.Name) %>
|
||||
</fieldset>
|
||||
<%:Html.EditorFor(m => m.Settings) %>
|
||||
<h2><%:T("Parts") %></h2>
|
||||
@@ -16,7 +18,7 @@ using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<%:Html.EditorFor(m => m.Parts, "Parts", "") %>
|
||||
<h2><%:T("Fields") %></h2>
|
||||
<div class="manage add-to-type"><%: Html.ActionLink(T("Add").Text, "AddField", new { }, new { @class = "button" })%></div>
|
||||
<%--<%:Html.EditorFor(m => m.Fields, "ContentTypeFields")%>--%>
|
||||
<%:Html.EditorFor(m => m.Fields, "Fields", "")%>
|
||||
<fieldset>
|
||||
<button class="primaryAction" type="submit"><%:T("Save") %></button>
|
||||
</fieldset><%
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
||||
<h1><%:Html.TitleForPage(T("Content Types").ToString())%></h1>
|
||||
<div class="manage"><%: Html.ActionLink(T("Create new type").ToString(), "CreateType", null, new { @class = "button primaryAction" })%></div>
|
||||
<%=Html.UnorderedList(
|
||||
<%:Html.UnorderedList(
|
||||
Model.Types,
|
||||
(t,i) => Html.DisplayFor(m => t),
|
||||
"contentItems"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.ContentManagement.MetaData.Models.ContentTypeDefinition>" %>
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ContentTypeDefinition>" %>
|
||||
<%@ Import namespace="Orchard.ContentManagement.MetaData.Models" %>
|
||||
<div class="summary">
|
||||
<div class="properties">
|
||||
<h3><%:Model.DisplayName%></h3>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<SettingsDictionary>" %>
|
||||
<%@ import Namespace="Orchard.ContentManagement.MetaData.Models" %>
|
||||
<dl><%
|
||||
foreach (var setting in Model) { %>
|
||||
<dt><%:setting.Key %></dt>
|
||||
<dd><%:setting.Value %></dd><%
|
||||
} %>
|
||||
</dl>
|
||||
@@ -1,14 +1,17 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ContentPartDefinition.Field>" %>
|
||||
<%@ Import Namespace="Orchard.ContentManagement.MetaData.Models" %>
|
||||
<fieldset>
|
||||
<h3><%:Model.FieldDefinition.Name %></h3>
|
||||
<div class="manage add-to-type">
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<EditPartFieldViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
||||
<fieldset class="manage-field">
|
||||
<h3><%:Model.Name %> <span>(<%:Model.FieldDefinition.Name %>)</span></h3>
|
||||
<div class="manage">
|
||||
<%--// these inline forms can't be here. should probably have some JavaScript in here to build up the forms and add the "remove" link.
|
||||
// get the antiforgery token from the edit type form and mark up the part in a semantic way so I can get some info from the DOM --%>
|
||||
<%:Html.Link("[remove]", "#forshowonlyandnotintendedtowork!") %>
|
||||
<%-- <% using (Html.BeginFormAntiForgeryPost(Url.Action("RemovePart", new { area = "Contents" }), FormMethod.Post, new {@class = "inline link"})) { %>
|
||||
<%=Html.Hidden("name", Model.PartDefinition.Name, new { id = "" }) %>
|
||||
<%:Html.Hidden("name", Model.PartDefinition.Name, new { id = "" }) %>
|
||||
<button type="submit" title="<%:T("Remove") %>"><%:T("Remove") %></button>
|
||||
<% } %> --%>
|
||||
</div>
|
||||
<%:Html.EditorFor(m => m.Settings, "Settings", "") %>
|
||||
<%:Html.HiddenFor(m => m.Name) %>
|
||||
<%:Html.HiddenFor(m => m.FieldDefinition.Name) %>
|
||||
</fieldset>
|
||||
@@ -0,0 +1,12 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<IEnumerable<EditPartFieldViewModel>>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><%
|
||||
if (Model.Any()) { %>
|
||||
<fieldset><%
|
||||
var fi = 0;
|
||||
foreach (var field in Model) {
|
||||
var f = field;
|
||||
var htmlFieldName = string.Format("Fields[{0}]", fi++); %>
|
||||
<%:Html.EditorFor(m => f, "Field", htmlFieldName) %><%
|
||||
} %>
|
||||
</fieldset><%
|
||||
} %>
|
||||
@@ -0,0 +1,6 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<EditPartFieldViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
||||
<dt><%:Model.Name %> <span>(<%:Model.FieldDefinition.Name %>)</span></dt>
|
||||
<dd>
|
||||
<%:Html.DisplayFor(m => m.Settings, "Settings", "") %>
|
||||
</dd>
|
||||
@@ -1,10 +1,10 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<IEnumerable<EditPartFieldViewModel>>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %><%
|
||||
if (Model.Any()) { %>
|
||||
<fieldset><%
|
||||
<dl><%
|
||||
foreach (var field in Model) {
|
||||
var f = field; %>
|
||||
<%:Html.EditorFor(m => f, "FieldOnPart") %><%
|
||||
<%:Html.EditorFor(m => f, "Part.Field") %><%
|
||||
} %>
|
||||
</fieldset><%
|
||||
</dl><%
|
||||
} %>
|
||||
@@ -1,8 +1,8 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<EditTypePartViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
||||
<fieldset>
|
||||
<fieldset class="manage-part">
|
||||
<h3><%:Model.PartDefinition.Name %></h3>
|
||||
<div class="manage add-to-type">
|
||||
<div class="manage">
|
||||
<%--// these inline forms can't be here. should probably have some JavaScript in here to build up the forms and add the "remove" link.
|
||||
// get the antiforgery token from the edit type form and mark up the part in a semantic way so I can get some info from the DOM --%>
|
||||
<%:Html.Link("[remove]", "#forshowonlyandnotintendedtowork") %>
|
||||
@@ -11,11 +11,12 @@
|
||||
<button type="submit" title="<%:T("Remove") %>"><%:T("Remove") %></button>
|
||||
<% } %> --%>
|
||||
</div>
|
||||
<%--
|
||||
what is this settings for?
|
||||
<%:Html.EditorFor(m => m.PartDefinition.Settings, "Settings") %>--%>
|
||||
<%:Html.EditorFor(m => m.Settings, "Settings", "") %>
|
||||
<%:Html.EditorFor(m => m.PartDefinition.Fields, "FieldsOnPart") %>
|
||||
<%:Html.Hidden("PartDefinition.Name", Model.PartDefinition.Name) %>
|
||||
<%:Html.EditorFor(m => m.Settings, "Settings", "") %><%
|
||||
if (Model.PartDefinition.Settings.Any() || Model.PartDefinition.Fields.Any()) { %>
|
||||
<h4><%:T("Global configuration") %></h4>
|
||||
<div class="manage minor"><%:Html.ActionLink(T("Edit").Text, "EditPart", new { area = "Contents", id = Model.PartDefinition.Name }) %></div>
|
||||
<%:Html.DisplayFor(m => m.PartDefinition.Settings, "Settings", "PartDefinition") %>
|
||||
<%:Html.EditorFor(m => m.PartDefinition.Fields, "Part.Fields") %><%
|
||||
} %>
|
||||
<%:Html.Hidden("PartDefinition.Name", Model.PartDefinition.Name) %>
|
||||
</fieldset>
|
||||
@@ -1,4 +1,5 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.ContentManagement.MetaData.Models.SettingsDictionary>" %><%
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<SettingsDictionary>" %>
|
||||
<%@ import Namespace="Orchard.ContentManagement.MetaData.Models" %><%
|
||||
if (Model.Any()) { %>
|
||||
<fieldset><%
|
||||
var si = 0;
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
<Content Include="Common\Views\EditorTemplates\Parts\Common.TextContentField.ascx" />
|
||||
<Content Include="Contents\Module.txt" />
|
||||
<Content Include="Contents\Styles\admin.css" />
|
||||
<Content Include="Contents\Views\Admin\EditPart.ascx" />
|
||||
<Content Include="Contents\Views\Admin\EditType.ascx" />
|
||||
<Content Include="Contents\Views\Admin\CreateType.ascx" />
|
||||
<Content Include="Contents\Views\Admin\Types.ascx" />
|
||||
@@ -217,9 +218,12 @@
|
||||
<Content Include="Contents\Views\Admin\Create.aspx" />
|
||||
<Content Include="Contents\Views\DisplayTemplates\ContentTypeDefinition.ascx" />
|
||||
<Content Include="Contents\Views\DisplayTemplates\Items\Contents.Item.ascx" />
|
||||
<Content Include="Contents\Views\DisplayTemplates\Settings.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Field.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Fields.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Settings.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\FieldsOnPart.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\FieldOnPart.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Part.Fields.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Part.Field.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Parts.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Part.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Items\Contents.Item.ascx" />
|
||||
|
||||
@@ -3,9 +3,11 @@ using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.DevTools.Commands {
|
||||
[OrchardFeature("Profiling")]
|
||||
public class ProfilingCommands : DefaultOrchardCommandHandler {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IMembershipService _membershipService;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Orchard.Commands;
|
||||
using Orchard.Environment.Extensions;
|
||||
|
||||
namespace Orchard.DevTools.Commands {
|
||||
[OrchardFeature("Scaffolding")]
|
||||
public class ScaffoldingCommands : DefaultOrchardCommandHandler {
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,13 @@ orchardversion: 0.1.2010.0312
|
||||
description: This module is not activated by default and should only be used in a development environment. It contains various debugging and tracing tools that can display information about your content types.
|
||||
features:
|
||||
Orchard.DevTools:
|
||||
Description: An assortment of debuging tools.
|
||||
Category: Developer
|
||||
Description: An assortment of debugging tools.
|
||||
Category: Developer
|
||||
Scaffolding:
|
||||
Description: Tools to create Orchard components.
|
||||
Category: Developer
|
||||
Dependencies: Orchard.DevTools
|
||||
Profiling:
|
||||
Description: Tools to help profile Orchard.
|
||||
Category: Developer
|
||||
Dependencies: Orchard.DevTools
|
||||
@@ -71,6 +71,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="AdminMenu.cs" />
|
||||
<Compile Include="Commands\ProfilingCommands.cs" />
|
||||
<Compile Include="Commands\ScaffoldingCommands.cs" />
|
||||
<Compile Include="Controllers\ContentController.cs" />
|
||||
<Compile Include="Controllers\HomeController.cs" />
|
||||
<Compile Include="Controllers\MetadataController.cs" />
|
||||
@@ -85,6 +86,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Module.txt" />
|
||||
<Content Include="ScaffoldingTemplates\Controller.txt" />
|
||||
<Content Include="ScaffoldingTemplates\ModuleAssemblyInfo.txt" />
|
||||
<Content Include="ScaffoldingTemplates\ModuleCsProj.txt" />
|
||||
<Content Include="ScaffoldingTemplates\ModuleManifest.txt" />
|
||||
<Content Include="ScaffoldingTemplates\ModuleWebConfig.txt" />
|
||||
<Content Include="Views\Home\_RenderableAction.ascx" />
|
||||
<Content Include="Views\Home\Simple.aspx" />
|
||||
<Content Include="Views\Content\Details.aspx" />
|
||||
@@ -106,6 +112,7 @@
|
||||
<Name>Orchard.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.$$ModuleName$$.Controllers {
|
||||
public class $$ControllerName$$ : Controller {
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public $$ControllerName$$(IOrchardServices services) {
|
||||
Services = services;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Orchard.$$ModuleName$$")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyProduct("Orchard")]
|
||||
[assembly: AssemblyCopyright("Copyright © CodePlex Foundation 2009")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("$$ModuleTypeLibGuid$$")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{$$ModuleProjectGuid$$}</ProjectGuid>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Orchard.$$ModuleName$$</RootNamespace>
|
||||
<AssemblyName>Orchard.$$ModuleName$$</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<MvcBuildViews>false</MvcBuildViews>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation />
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.Web.DynamicData" />
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Abstractions" />
|
||||
<Reference Include="System.Web.Routing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.EnterpriseServices" />
|
||||
<Reference Include="System.Web.Mobile" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Module.txt" />
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Core\Orchard.Core.csproj">
|
||||
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
|
||||
<Name>Orchard.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target> -->
|
||||
<!-- To enable MVC area subproject support, uncomment the following two lines:
|
||||
<UsingTask TaskName="Microsoft.Web.Mvc.Build.CreateAreaManifest" AssemblyName="Microsoft.Web.Mvc.Build, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<UsingTask TaskName="Microsoft.Web.Mvc.Build.CopyAreaManifests" AssemblyName="Microsoft.Web.Mvc.Build, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
-->
|
||||
<Target Name="AfterBuild" DependsOnTargets="AfterBuildCompiler">
|
||||
<PropertyGroup>
|
||||
<AreasManifestDir>$(ProjectDir)\..\Manifests</AreasManifestDir>
|
||||
</PropertyGroup>
|
||||
<!-- If this is an area child project, uncomment the following line:
|
||||
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Child" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
|
||||
-->
|
||||
<!-- If this is an area parent project, uncomment the following lines:
|
||||
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Parent" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
|
||||
<CopyAreaManifests ManifestPath="$(AreasManifestDir)" CrossCopy="false" RenameViews="true" />
|
||||
-->
|
||||
</Target>
|
||||
<Target Name="AfterBuildCompiler" Condition="'$(MvcBuildViews)'=='true'">
|
||||
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
|
||||
</Target>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>False</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>45979</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>
|
||||
</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>True</UseCustomServer>
|
||||
<CustomServerUrl>http://orchard.codeplex.com</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
@@ -0,0 +1,5 @@
|
||||
name: $$ModuleName$$
|
||||
antiforgery: enabled
|
||||
features:
|
||||
Orchard.$$ModuleName$$:
|
||||
Description: Description for feature $$ModuleName$$.
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Note: As an alternative to hand editing this file you can use the
|
||||
web admin tool to configure settings for your application. Use
|
||||
the Website->Asp.Net Configuration option in Visual Studio.
|
||||
A full list of settings and comments can be found in
|
||||
machine.config.comments usually located in
|
||||
\Windows\Microsoft.Net\Framework\v2.x\Config
|
||||
-->
|
||||
<configuration>
|
||||
<system.web>
|
||||
<!--
|
||||
Set compilation debug="true" to insert debugging
|
||||
symbols into the compiled page. Because this
|
||||
affects performance, set this value to true only
|
||||
during development.
|
||||
-->
|
||||
<compilation debug="true" targetFramework="4.0">
|
||||
<assemblies>
|
||||
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
|
||||
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
|
||||
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
|
||||
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/></assemblies>
|
||||
</compilation>
|
||||
<!--
|
||||
The <customErrors> section enables configuration
|
||||
of what to do if/when an unhandled error occurs
|
||||
during the execution of a request. Specifically,
|
||||
it enables developers to configure html error pages
|
||||
to be displayed in place of a error stack trace.
|
||||
|
||||
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
|
||||
<error statusCode="403" redirect="NoAccess.htm" />
|
||||
<error statusCode="404" redirect="FileNotFound.htm" />
|
||||
</customErrors>
|
||||
-->
|
||||
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
|
||||
<namespaces>
|
||||
<add namespace="System.Web.Mvc"/>
|
||||
<add namespace="System.Web.Mvc.Ajax"/>
|
||||
<add namespace="System.Web.Mvc.Html"/>
|
||||
<add namespace="System.Web.Routing"/>
|
||||
<add namespace="System.Linq"/>
|
||||
<add namespace="System.Collections.Generic"/>
|
||||
<add namespace="Orchard.Mvc.Html"/>
|
||||
</namespaces>
|
||||
</pages>
|
||||
<httpHandlers>
|
||||
<add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
|
||||
</httpHandlers>
|
||||
</system.web>
|
||||
<system.web.extensions/>
|
||||
<!--
|
||||
The system.webServer section is required for running ASP.NET AJAX under Internet
|
||||
Information Services 7.0. It is not necessary for previous version of IIS.
|
||||
-->
|
||||
<system.webServer>
|
||||
<validation validateIntegratedModeConfiguration="false"/>
|
||||
<modules runAllManagedModulesForAllRequests="true">
|
||||
</modules>
|
||||
<handlers>
|
||||
<remove name="MvcHttpHandler"/>
|
||||
<remove name="UrlRoutingHandler"/>
|
||||
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -147,10 +147,11 @@ h1 { font-size:2.6em; } /* 26px */
|
||||
h2 { font-size:2.1em; } /* 21px */
|
||||
h2 span { font-size:.57em; } /* 12px */
|
||||
h3 { font-size:1.8em; } /* 18px */
|
||||
h3 span { font-size:.667em; } /* 12px */
|
||||
h4 { font-size:1.6em; } /* 16px */
|
||||
h5 { font-size:1.4em; } /* 14px */
|
||||
|
||||
h6, p, label, /*input, select,*/ .button,
|
||||
h6, p, dl, label, /*input, select,*/ .button,
|
||||
.message, .validation-summary-errors,
|
||||
table.items th, table.items td, table.items caption { font-size:1.4em; line-height:1.4em; } /* 14px */
|
||||
table.items p, table.items label, table.items input, table.items .button { font-size:1em; line-height:1em; }
|
||||
@@ -510,7 +511,6 @@ button.remove:focus::-moz-focus-inner, .remove.button:focus::-moz-focus-inner {
|
||||
.manage {
|
||||
float:right;
|
||||
margin:0 0 10px 8px;
|
||||
overflow:hidden;
|
||||
}
|
||||
.actions {
|
||||
clear:right;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Orchard.DataMigration.Commands {
|
||||
[OrchardSwitches("Feature")]
|
||||
public string UpgradeDatabase() {
|
||||
try {
|
||||
_dataMigrationManager.Upgrade(Feature);
|
||||
_dataMigrationManager.Update(Feature);
|
||||
}
|
||||
catch ( Exception ex ) {
|
||||
Context.Output.WriteLine(T("An error occured while upgrading the database: " + ex.Message));
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
namespace Orchard.DataMigration {
|
||||
public abstract class DataMigration : IDataMigration {
|
||||
using Orchard.DataMigration.Schema;
|
||||
|
||||
namespace Orchard.DataMigration {
|
||||
/// <summary>
|
||||
/// Data Migration classes can inherit from this class to get a SchemaBuilder instance configured with the current tenant database prefix
|
||||
/// </summary>
|
||||
public abstract class DataMigrationImpl : IDataMigration {
|
||||
public abstract string Feature { get; }
|
||||
public SchemaBuilder SchemaBuilder { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
40
src/Orchard/DataMigration/DataMigrationCoordinator.cs
Normal file
40
src/Orchard/DataMigration/DataMigrationCoordinator.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.DataMigration {
|
||||
/// <summary>
|
||||
/// Responsible for executing data migration tasks when a feature is enabled for the first time
|
||||
/// 1) Initial install of a module:
|
||||
/// Enable a feature for the first time => run data migration up to the latest version
|
||||
/// Enable a feature on 2nd time => no data migration run
|
||||
/// Disable a feature => no data migration
|
||||
/// 2) Installing a newer version of a module
|
||||
/// Don't do any data migration by default
|
||||
/// 2 cases:
|
||||
/// 1) feature wasn't not enabled when new code was installed
|
||||
/// 2) feature was enabled when new code was installed
|
||||
/// </summary>
|
||||
public class DataMigrationCoordinator : IFeatureEventHandler {
|
||||
private readonly IDataMigrationManager _dataMigrationManager;
|
||||
|
||||
public DataMigrationCoordinator(IDataMigrationManager dataMigrationManager) {
|
||||
_dataMigrationManager = dataMigrationManager;
|
||||
}
|
||||
|
||||
public void Install(Feature feature) {
|
||||
var featureName = feature.Descriptor.Name;
|
||||
if ( !_dataMigrationManager.IsFeatureAlreadyInstalled(featureName) ) {
|
||||
_dataMigrationManager.Update(featureName);
|
||||
}
|
||||
}
|
||||
|
||||
public void Enable(Feature feature) {
|
||||
}
|
||||
|
||||
public void Disable(Feature feature) {
|
||||
}
|
||||
|
||||
public void Uninstall(Feature feature) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,10 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Orchard.Data;
|
||||
using Orchard.DataMigration.Schema;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.State;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.DataMigration {
|
||||
@@ -17,34 +19,77 @@ namespace Orchard.DataMigration {
|
||||
private readonly IRepository<DataMigrationRecord> _dataMigrationRepository;
|
||||
private readonly IDataMigrationGenerator _dataMigrationGenerator;
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
|
||||
public DataMigrationManager(
|
||||
IEnumerable<IDataMigration> dataMigrations,
|
||||
IRepository<DataMigrationRecord> dataMigrationRepository,
|
||||
IDataMigrationGenerator dataMigrationGenerator,
|
||||
IExtensionManager extensionManager) {
|
||||
IExtensionManager extensionManager,
|
||||
ShellSettings shellSettings) {
|
||||
_dataMigrations = dataMigrations;
|
||||
_dataMigrationRepository = dataMigrationRepository;
|
||||
_dataMigrationGenerator = dataMigrationGenerator;
|
||||
_extensionManager = extensionManager;
|
||||
_shellSettings = shellSettings;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void Upgrade(string feature) {
|
||||
public IEnumerable<string> GetFeaturesThatNeedUpdate() {
|
||||
|
||||
var features = new List<string>();
|
||||
|
||||
// compare current version and available migration methods for each migration class
|
||||
foreach ( var dataMigration in _dataMigrations ) {
|
||||
|
||||
// get current version for this migration
|
||||
var dataMigrationRecord = GetDataMigrationRecord(dataMigration);
|
||||
|
||||
var current = 0;
|
||||
if (dataMigrationRecord != null) {
|
||||
current = dataMigrationRecord.Current;
|
||||
}
|
||||
|
||||
// do we need to call Create() ?
|
||||
if (current == 0) {
|
||||
|
||||
// try to resolve a Create method
|
||||
if ( GetCreateMethod(dataMigration) != null ) {
|
||||
features.Add(dataMigration.Feature);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var lookupTable = CreateUpgradeLookupTable(dataMigration);
|
||||
|
||||
if(lookupTable.ContainsKey(current)) {
|
||||
features.Add(dataMigration.Feature);
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<string> features) {
|
||||
foreach(var feature in features) {
|
||||
Update(feature);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(string feature){
|
||||
|
||||
// proceed with dependent features first, whatever the module it's in
|
||||
var dependencies = _extensionManager
|
||||
.AvailableExtensions()
|
||||
.SelectMany(e => e.Features)
|
||||
var dependencies = ShellStateCoordinator.OrderByDependencies(_extensionManager.AvailableExtensions()
|
||||
.SelectMany(ext => ext.Features))
|
||||
.Where(f => String.Equals(f.Name, feature, StringComparison.OrdinalIgnoreCase))
|
||||
.Where(f => f.Dependencies != null)
|
||||
.SelectMany( f => f.Dependencies )
|
||||
.ToList();
|
||||
|
||||
foreach(var dependency in dependencies) {
|
||||
Upgrade(dependency);
|
||||
Update(dependency);
|
||||
}
|
||||
|
||||
var migrations = GetDataMigrations(feature);
|
||||
@@ -55,11 +100,8 @@ namespace Orchard.DataMigration {
|
||||
var tempMigration = migration;
|
||||
|
||||
// get current version for this migration
|
||||
var dataMigrationRecord = _dataMigrationRepository.Table
|
||||
.Where(dm => dm.DataMigrationClass == tempMigration.GetType().FullName)
|
||||
.FirstOrDefault();
|
||||
var dataMigrationRecord = GetDataMigrationRecord(tempMigration);
|
||||
|
||||
var updateMethodNameRegex = new Regex(@"^UpdateFrom(?<version>\d+)$", RegexOptions.Compiled);
|
||||
var current = 0;
|
||||
if(dataMigrationRecord != null) {
|
||||
current = dataMigrationRecord.Current;
|
||||
@@ -69,8 +111,8 @@ namespace Orchard.DataMigration {
|
||||
if(current == 0) {
|
||||
// try to resolve a Create method
|
||||
|
||||
var createMethod = migration.GetType().GetMethod("Create", BindingFlags.Public | BindingFlags.Instance);
|
||||
if(createMethod != null && createMethod.ReturnType == typeof(int)) {
|
||||
var createMethod = GetCreateMethod(migration);
|
||||
if(createMethod != null) {
|
||||
current = (int)createMethod.Invoke(migration, new object[0]);
|
||||
}
|
||||
else {
|
||||
@@ -79,15 +121,7 @@ namespace Orchard.DataMigration {
|
||||
}
|
||||
}
|
||||
|
||||
// update methods might also be called after Create()
|
||||
var lookupTable = new Dictionary<int, MethodInfo>();
|
||||
// construct a lookup table with all managed initial versions
|
||||
foreach(var methodInfo in migration.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance)) {
|
||||
var match = updateMethodNameRegex.Match(methodInfo.Name);
|
||||
if(match.Success) {
|
||||
lookupTable.Add(int.Parse(match.Groups["version"].Value), methodInfo);
|
||||
}
|
||||
}
|
||||
var lookupTable = CreateUpgradeLookupTable(migration);
|
||||
|
||||
while(lookupTable.ContainsKey(current)) {
|
||||
try {
|
||||
@@ -96,29 +130,82 @@ namespace Orchard.DataMigration {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "An unexpected error orccured while applying migration on {0} from version {1}", feature, current);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// if current is 0, it means no upgrade/create method was found or succeeded
|
||||
if ( current != 0 ) {
|
||||
if (dataMigrationRecord == null) {
|
||||
_dataMigrationRepository.Create(new DataMigrationRecord {Current = current, DataMigrationClass = migration.GetType().FullName});
|
||||
}
|
||||
else {
|
||||
dataMigrationRecord.Current = current;
|
||||
_dataMigrationRepository.Update(dataMigrationRecord);
|
||||
}
|
||||
if (current == 0) {
|
||||
continue;
|
||||
}
|
||||
if (dataMigrationRecord == null) {
|
||||
_dataMigrationRepository.Create(new DataMigrationRecord {Current = current, DataMigrationClass = migration.GetType().FullName});
|
||||
}
|
||||
else {
|
||||
dataMigrationRecord.Current = current;
|
||||
_dataMigrationRepository.Update(dataMigrationRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DataMigrationRecord GetDataMigrationRecord(IDataMigration tempMigration) {
|
||||
return _dataMigrationRepository.Table
|
||||
.Where(dm => dm.DataMigrationClass == tempMigration.GetType().FullName)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all the available IDataMigration instances for a specific module
|
||||
/// Returns all the available IDataMigration instances for a specific module, and inject necessary builders
|
||||
/// </summary>
|
||||
public IEnumerable<IDataMigration> GetDataMigrations(string feature) {
|
||||
return _dataMigrations
|
||||
private IEnumerable<IDataMigration> GetDataMigrations(string feature) {
|
||||
var migrations = _dataMigrations
|
||||
.Where(dm => String.Equals(dm.Feature, feature, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
foreach (var migration in migrations.OfType<DataMigrationImpl>()) {
|
||||
migration.SchemaBuilder = new SchemaBuilder(_shellSettings.DataTablePrefix);
|
||||
}
|
||||
|
||||
return migrations;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether a feature has already been installed, i.e. one of its Data Migration class has already been processed
|
||||
/// </summary>
|
||||
public bool IsFeatureAlreadyInstalled(string feature) {
|
||||
return GetDataMigrations(feature).Any(dataMigration => GetDataMigrationRecord(dataMigration) != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a list of all available Update methods from a data migration class, indexed by the version number
|
||||
/// </summary>
|
||||
private static Dictionary<int, MethodInfo> CreateUpgradeLookupTable(IDataMigration dataMigration) {
|
||||
var updateMethodNameRegex = new Regex(@"^UpdateFrom(?<version>\d+)$", RegexOptions.Compiled);
|
||||
|
||||
// update methods might also be called after Create()
|
||||
var lookupTable = new Dictionary<int, MethodInfo>();
|
||||
|
||||
// construct a lookup table with all managed initial versions
|
||||
foreach ( var methodInfo in dataMigration.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance) ) {
|
||||
var match = updateMethodNameRegex.Match(methodInfo.Name);
|
||||
if ( match.Success ) {
|
||||
lookupTable.Add(int.Parse(match.Groups["version"].Value), methodInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return lookupTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Create metho from a data migration class if it's found
|
||||
/// </summary>
|
||||
private static MethodInfo GetCreateMethod(IDataMigration dataMigration) {
|
||||
var methodInfo = dataMigration.GetType().GetMethod("Create", BindingFlags.Public | BindingFlags.Instance);
|
||||
if(methodInfo != null && methodInfo.ReturnType == typeof(int)) {
|
||||
return methodInfo;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DataMigration {
|
||||
public interface IDataMigrationManager : IDependency {
|
||||
void Upgrade(string feature);
|
||||
/// <summary>
|
||||
/// Whether a feature has already been installed, i.e. one of its Data Migration class has already been processed
|
||||
/// </summary>
|
||||
bool IsFeatureAlreadyInstalled(string feature);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the features which have at least one Data Migration class with a corresponding Upgrade method to be called
|
||||
/// </summary>
|
||||
IEnumerable<string> GetFeaturesThatNeedUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// Updates the database to the latest version for the specified feature
|
||||
/// </summary>
|
||||
void Update(string feature);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the database to the latest version for the specified features
|
||||
/// </summary>
|
||||
void Update(IEnumerable<string> features);
|
||||
}
|
||||
}
|
||||
15
src/Orchard/DataMigration/Schema/AlterColumnCommand.cs
Normal file
15
src/Orchard/DataMigration/Schema/AlterColumnCommand.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class AlterColumnCommand : ColumnCommand {
|
||||
private string _newName;
|
||||
|
||||
public AlterColumnCommand(string name)
|
||||
: base(name) {
|
||||
}
|
||||
|
||||
|
||||
public AlterColumnCommand Rename(string name) {
|
||||
_newName = name;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
src/Orchard/DataMigration/Schema/AlterTableCommand.cs
Normal file
64
src/Orchard/DataMigration/Schema/AlterTableCommand.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class AlterTableCommand : SchemaCommand {
|
||||
public AlterTableCommand(string name)
|
||||
: base(name) {
|
||||
}
|
||||
|
||||
public AlterTableCommand AddColumn(string name, DbType dbType, Action<CreateColumnCommand> column = null) {
|
||||
var command = new CreateColumnCommand(name);
|
||||
command.Type(dbType);
|
||||
|
||||
if(column != null) {
|
||||
column(command);
|
||||
}
|
||||
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlterTableCommand DropColumn(string name) {
|
||||
var command = new DropColumnCommand(name);
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlterTableCommand AlterColumn(string name, Action<AlterColumnCommand> column = null) {
|
||||
var command = new AlterColumnCommand(name);
|
||||
|
||||
if ( column != null ) {
|
||||
column(command);
|
||||
}
|
||||
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlterTableCommand CreateIndex(string name, params string[] columnNames) {
|
||||
var command = new CreateIndexCommand(name, columnNames);
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlterTableCommand DropIndex(string name) {
|
||||
var command = new DropIndexCommand(name);
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlterTableCommand AddForeignKey(string name, Action<CreateForeignKeyCommand> fk) {
|
||||
var command = new CreateForeignKeyCommand(name);
|
||||
fk(command);
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlterTableCommand DropForeignKey(string name) {
|
||||
var command = new DropForeignKeyCommand(name);
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/Orchard/DataMigration/Schema/ColumnCommand.cs
Normal file
23
src/Orchard/DataMigration/Schema/ColumnCommand.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Data;
|
||||
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class ColumnCommand : TableCommand {
|
||||
private DbType _dbType;
|
||||
private object _default;
|
||||
public ColumnCommand(string name) : base(name) {
|
||||
_dbType = DbType.Object;
|
||||
_default = null;
|
||||
}
|
||||
|
||||
public ColumnCommand Type(DbType dbType) {
|
||||
_dbType = dbType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColumnCommand Default(object @default) {
|
||||
_default = @default;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
60
src/Orchard/DataMigration/Schema/CreateColumnCommand.cs
Normal file
60
src/Orchard/DataMigration/Schema/CreateColumnCommand.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class CreateColumnCommand : ColumnCommand {
|
||||
private bool _primaryKey;
|
||||
private byte? _precision;
|
||||
private byte? _scale;
|
||||
private int? _length;
|
||||
private bool _notNull;
|
||||
private bool _unique;
|
||||
|
||||
|
||||
public CreateColumnCommand(string name) : base(name) {
|
||||
_precision = null;
|
||||
_scale = null;
|
||||
_length = null;
|
||||
_notNull = false;
|
||||
_unique = false;
|
||||
|
||||
}
|
||||
|
||||
public CreateColumnCommand PrimaryKey() {
|
||||
_primaryKey = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateColumnCommand Precision(byte? precision) {
|
||||
_precision = precision;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateColumnCommand Scale(byte? scale) {
|
||||
_scale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateColumnCommand Length(int? length) {
|
||||
_length = length;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateColumnCommand NotNull() {
|
||||
_notNull = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateColumnCommand Nullable() {
|
||||
_notNull = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateColumnCommand Unique() {
|
||||
_unique = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateColumnCommand NotUnique() {
|
||||
_unique = false;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/Orchard/DataMigration/Schema/CreateForeignKeyCommand.cs
Normal file
31
src/Orchard/DataMigration/Schema/CreateForeignKeyCommand.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class CreateForeignKeyCommand : TableCommand {
|
||||
protected readonly List<ForeignKeyClause> _foreignKeyClauses;
|
||||
|
||||
public CreateForeignKeyCommand(string name)
|
||||
: base(name) {
|
||||
_foreignKeyClauses = new List<ForeignKeyClause>();
|
||||
}
|
||||
|
||||
public CreateForeignKeyCommand On(string srcColumn, string destTable, string destColumn) {
|
||||
_foreignKeyClauses.Add(new ForeignKeyClause(srcColumn, destTable, destColumn));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class ForeignKeyClause {
|
||||
public ForeignKeyClause(string srcColumn, string destTable, string destColumn) {
|
||||
SrcColumn = srcColumn;
|
||||
DestTable = destTable;
|
||||
DestColumn = destColumn;
|
||||
}
|
||||
|
||||
public string DestColumn { get; private set; }
|
||||
|
||||
public string DestTable { get; private set; }
|
||||
|
||||
public string SrcColumn { get; private set; }
|
||||
}
|
||||
}
|
||||
10
src/Orchard/DataMigration/Schema/CreateIndexCommand.cs
Normal file
10
src/Orchard/DataMigration/Schema/CreateIndexCommand.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class CreateIndexCommand : TableCommand {
|
||||
public CreateIndexCommand(string name, params string[] columnNames)
|
||||
: base(name) {
|
||||
ColumnNames = columnNames;
|
||||
}
|
||||
|
||||
public string[] ColumnNames { get; private set; }
|
||||
}
|
||||
}
|
||||
38
src/Orchard/DataMigration/Schema/CreateTableCommand.cs
Normal file
38
src/Orchard/DataMigration/Schema/CreateTableCommand.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class CreateTableCommand : SchemaCommand {
|
||||
public CreateTableCommand(string name)
|
||||
: base(name) {
|
||||
}
|
||||
|
||||
public CreateTableCommand Column(string name, DbType dbType, Action<CreateColumnCommand> column = null) {
|
||||
var command = new CreateColumnCommand(name);
|
||||
command.Type(dbType);
|
||||
|
||||
if ( column != null ) {
|
||||
column(command);
|
||||
}
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateTableCommand ContentPartRecord() {
|
||||
/// TODO: Call Column() with necessary information for content part records
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateTableCommand VersionedContentPartRecord() {
|
||||
/// TODO: Call Column() with necessary information for content part records
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateTableCommand ForeignKey(string name, Action<CreateForeignKeyCommand> fk) {
|
||||
var command = new CreateForeignKeyCommand(name);
|
||||
fk(command);
|
||||
_tableCommands.Add(command);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/Orchard/DataMigration/Schema/DropColumnCommand.cs
Normal file
8
src/Orchard/DataMigration/Schema/DropColumnCommand.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class DropColumnCommand : ColumnCommand {
|
||||
public DropColumnCommand(string name)
|
||||
: base(name) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class DropForeignKeyCommand : TableCommand {
|
||||
|
||||
public DropForeignKeyCommand(string name)
|
||||
: base(name) {
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/Orchard/DataMigration/Schema/DropIndexCommand.cs
Normal file
8
src/Orchard/DataMigration/Schema/DropIndexCommand.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class DropIndexCommand : TableCommand {
|
||||
|
||||
public DropIndexCommand(string name)
|
||||
: base(name) {
|
||||
}
|
||||
}
|
||||
}
|
||||
7
src/Orchard/DataMigration/Schema/DropTableCommand.cs
Normal file
7
src/Orchard/DataMigration/Schema/DropTableCommand.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class DropTableCommand : SchemaCommand {
|
||||
public DropTableCommand(string name)
|
||||
: base(name) {
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/Orchard/DataMigration/Schema/SchemaBuilder.cs
Normal file
46
src/Orchard/DataMigration/Schema/SchemaBuilder.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class SchemaBuilder {
|
||||
|
||||
private readonly List<SchemaCommand> _schemaCommands;
|
||||
|
||||
public SchemaBuilder() {
|
||||
_schemaCommands = new List<SchemaCommand>();
|
||||
}
|
||||
|
||||
public SchemaBuilder(string tablePrefix) : this() {
|
||||
TablePrefix = tablePrefix;
|
||||
}
|
||||
|
||||
public string TablePrefix { get; private set; }
|
||||
|
||||
public SchemaBuilder CreateTable(string name, Action<CreateTableCommand> table) {
|
||||
var createTable = new CreateTableCommand(name);
|
||||
table(createTable);
|
||||
_schemaCommands.Add(createTable);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SchemaBuilder AlterTable(string name, Action<AlterTableCommand> table) {
|
||||
var alterTable = new AlterTableCommand(name);
|
||||
table(alterTable);
|
||||
_schemaCommands.Add(alterTable);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SchemaBuilder DropTable(string name) {
|
||||
var deleteTable = new DropTableCommand(name);
|
||||
_schemaCommands.Add(deleteTable);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SchemaBuilder ExecuteSql(string sql, Action<SqlStatementCommand> statement) {
|
||||
var sqlStatmentCommand = new SqlStatementCommand(sql);
|
||||
statement(sqlStatmentCommand);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
19
src/Orchard/DataMigration/Schema/SchemaCommand.cs
Normal file
19
src/Orchard/DataMigration/Schema/SchemaCommand.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class SchemaCommand {
|
||||
protected readonly List<TableCommand> _tableCommands;
|
||||
|
||||
public SchemaCommand(string tableName) {
|
||||
_tableCommands = new List<TableCommand>();
|
||||
Name(tableName);
|
||||
}
|
||||
|
||||
public string TableName { get; private set; }
|
||||
|
||||
public SchemaCommand Name(string name) {
|
||||
TableName = name;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Orchard/DataMigration/Schema/SqlStatementCommand.cs
Normal file
19
src/Orchard/DataMigration/Schema/SqlStatementCommand.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class SqlStatementCommand : SchemaCommand {
|
||||
protected readonly List<string> _dialects;
|
||||
public SqlStatementCommand(string sql)
|
||||
: base("") {
|
||||
Sql = sql;
|
||||
_dialects = new List<string>();
|
||||
}
|
||||
|
||||
public string Sql { get; private set; }
|
||||
|
||||
public SqlStatementCommand ForDialect(string dialect) {
|
||||
_dialects.Add(dialect);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/Orchard/DataMigration/Schema/TableCommand.cs
Normal file
10
src/Orchard/DataMigration/Schema/TableCommand.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Orchard.DataMigration.Schema {
|
||||
public class TableCommand {
|
||||
private string _name;
|
||||
|
||||
public TableCommand(string name) {
|
||||
_name = name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ namespace Orchard.Environment.State {
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<FeatureDescriptor> OrderByDependencies(IEnumerable<FeatureDescriptor> descriptors) {
|
||||
public static IEnumerable<FeatureDescriptor> OrderByDependencies(IEnumerable<FeatureDescriptor> descriptors) {
|
||||
var population = descriptors.Select(d => new Linkage {
|
||||
Feature = d
|
||||
}).ToArray();
|
||||
|
||||
@@ -349,7 +349,19 @@
|
||||
<Compile Include="ContentManagement\ViewModels\TemplateViewModel.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="DataMigration\Schema\SqlStatementCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\CreateColumnCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\CreateForeignKeyCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\DropForeignKeyCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\DropIndexCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\CreateIndexCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\DropColumnCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\AlterColumnCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\DropTableCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\AlterTableCommand.cs" />
|
||||
<Compile Include="DataMigration\Commands\DataMigrationCommands.cs" />
|
||||
<Compile Include="DataMigration\Schema\SchemaBuilder.cs" />
|
||||
<Compile Include="DataMigration\DataMigrationCoordinator.cs" />
|
||||
<Compile Include="DataMigration\IDataMigrationCommand.cs" />
|
||||
<Compile Include="DataMigration\DefaultDataMigrationGenerator.cs" />
|
||||
<Compile Include="DataMigration\IDataMigrationGenerator.cs" />
|
||||
@@ -358,6 +370,10 @@
|
||||
<Compile Include="DataMigration\DataMigrationRecord.cs" />
|
||||
<Compile Include="DataMigration\IDataMigration.cs" />
|
||||
<Compile Include="DataMigration\IDataMigrationManager.cs" />
|
||||
<Compile Include="DataMigration\Schema\ColumnCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\CreateTableCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\TableCommand.cs" />
|
||||
<Compile Include="DataMigration\Schema\SchemaCommand.cs" />
|
||||
<Compile Include="Data\SessionLocator.cs" />
|
||||
<Compile Include="Data\IRepository.cs" />
|
||||
<Compile Include="Data\ISessionLocator.cs" />
|
||||
|
||||
Reference in New Issue
Block a user